Interpreting C pointers, dereferencing and indirection

  • Thread starter Thread starter Basher1
  • Start date Start date
  • Tags Tags
    Pointers
AI Thread Summary
The discussion focuses on interpreting C pointers, particularly in the context of embedded development. The use of the `#define INPUT` statement illustrates how to access a specific memory address as a volatile unsigned long, ensuring the compiler does not optimize out necessary reads. The first asterisk in expressions like `*(long*)pt = NULL` indicates dereferencing, allowing the assignment of a NULL value to the memory location pointed to by `pt`, which is cast to a long pointer. The second expression, `FreePt = (long*)*pt`, retrieves the value pointed to by `pt` and assigns it to `FreePt`, which is also a long pointer. Understanding these concepts is crucial for effective manipulation of memory in C programming, especially in embedded systems.
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 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.
 
Back
Top