Interpreting C pointers, dereferencing and indirection

  • Thread starter Thread starter Basher1
  • Start date Start date
  • Tags Tags
    Pointers
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
3 replies · 3K views
Basher1
Messages
27
Reaction score
0
I have been going through a book on embedded development. I have been followin the C programs in the book with about 95% success as C is not completely new to me. But I am new to pointers so I was hoping someone would kindly clear a few things for me.

#define INPUT (*((volatile unsigned long *)0x40004004))

the hex number 0x40004004 represents the address of an general purpose I/O port for a microcontroller. Now I know that one of the * symbols(I don't know exactly which one, but I am guessing the first one from the left) represents the indirection operator which treats the address as an address and not a literal number. I also know that the volatile unsigned long is used so the compiler knows it needs to read a 32-bit unsigned number from the address. But I don't know why the there is another * in this statement.

another two examples that are leaving me stumped

*(long*)pt = NULL

and

FreePt = (long*)*pt

how do I interpret these?
 
Physics news on Phys.org
The first star is saying that the variable is a pointer and the parenthetical (long *) is casting the variable to be a volatile unsigned long pointer. Volatile means the compiler should leave it alone and not optimize code related to it and unsigned long pointer.

http://en.wikipedia.org/wiki/Volatile_variable

I'd say the statement *(long*)pt = NULL means store a NULL value into the memory location where the pt points and to store a long value (4 bytes for some C systems) ie fill it with 4 bytes of zeros.

Similarly the statement FreePt = (long*)*pt tells the computer to get the value pointed at by pt and store it in FreePt. the (long *) says the value is in fact a long pointer so you're using a pointer to retrieve a pointer and assigning it to FreePt so somewhere in your code you should see a declaration for FreePt as long *FreePt;

Here's some more on pointers and advanced pointers:

http://www.thegeekstuff.com/2011/12/c-pointers-fundamentals/
 
Last edited:
  • Like
Likes   Reactions: 1 person
Basher1 said:
#define INPUT (*((volatile unsigned long *)0x40004004))
"INPUT" could be used as follows:
Code:
{
  unsigned long ulLatestInput1, ulLatestInput2;

  ulLatestInput1 = INPUT;
  ulLatestInput2 = INPUT;
  if(ulLatestInput1==ulLatestInput2) ...
}
Interpreted as follows:
Hex value 0x40004004 is being cast as a volatile pointer to an unsigned long value. So, there is a 32 bit value at memory address 0x40004004. The fact that it is being declared "volatile" indicates that it can change at any moment. If there "volatile" was not declared, then in the my code snippet above the compiler might optimize the code to effectively "ulLatestInput2 = ulLatestInput1 = INPUT;" so that the "if" would always evaluate to true. The "volatile" declaration would prevent this optimization so that the memory location was reexamined before setting "ulLatestInput2".

The other asterisk is the first one. The term "((volatile unsigned long *)0x40004004)" is a pointer to a memory location. If you want to read that value, your need to preceded it with an asterisk or follow is with "[0]".

Basher1 said:
*(long*)pt = NULL

FreePt = (long*)*pt
In the first statement, there is a pointer "pt". You haven't specified its type, but I will presume it to be a short pointer ("short *"), and is pointing into an array of short values.
So in the first statement, the "(long *)" is causing "pt" to be recast as a long pointer. It's processor dependent, but this probably means it's being interpreted as pointing to a 32-bit value instead of a 16-bit value. Consider this code:
Code:
{
#define NULL (0)
  short naArray[5], *pt;

  pt = naArray+2;
  *(long *)pt = NULL;
}
So we have set pt to point to the third element in array "naArray". Exactly what happens with "*(long *)pt = NULL;" depends of whether the machine you are working on is Big Endian or Little Endian. In both cases, naArray[2] is set to zero, but since "(long *)pt" points to a 32-bit value, either naArray[1] or naArray[3] will also be set to zero - depending on your computer's Endian.

FreePt must have been declared "long *". It is being set to point to the same value that was just "NULL"ed in the previous statement.
 
Thats the thing. He's already declared "*Pt" as long. Sorry, I should have specified this information.