Discuss Expression Clarification in the C Programming forum on Dev Shed. Expression Clarification C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
Posts: 21
Time spent in forums: 6 h 44 m 11 sec
Reputation Power: 0
Expression Clarification
Hi Guys,
still having a few issues with pointers...
I came across this expression that obviously works and I can even see what it is doing, but I can not get my head around it.
for the ARM uC I am using they have this definition:
#define PB8 (*((volatile unsigned long *) 0x422181A0))
and then the usage is so:
PB8 = 1;
can some one explain/breakdown the #define expression and what it means when you use it.
this is sort of my interpretation of it:
- (volatile unsigned long *) creates the pointer (without a name?)
- (volatile unsigned long *) 0x422181A0) assigns the address being pointed at.
- (*((volatile unsigned long *) 0x422181A0)) is actually the value stored at address.
I probably got it completely wrong...
any info relating to this usage would be appreciated.
Posts: 5,538
Time spent in forums: 2 Weeks 4 Days 2 h 38 m 46 sec
Reputation Power: 242
There are more hardware oriented guys here who will probably correct me, but I believe this is creating an alias for a hardware address on the board somewhere. The stars and parentheses are to protect the expression from the compiler (#defines are plain textual substitutions) so that the compiler is happy. As a by the by, this sort of stuff will probably break when ARM64 is available.
It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
--Me, I just made it up
The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
--George Bernard Shaw
Location: Woodland Hills, Los Angeles County, California, USA
Posts: 9,382
Time spent in forums: 1 Month 4 Weeks 1 Day 20 h 31 m 48 sec
Reputation Power: 4080
Quote:
Originally Posted by lasm
Hi Guys,
still having a few issues with pointers...
I came across this expression that obviously works and I can even see what it is doing, but I can not get my head around it.
for the ARM uC I am using they have this definition:
#define PB8 (*((volatile unsigned long *) 0x422181A0))
and then the usage is so:
PB8 = 1;
This means, write the value 1 to the memory address 0x422181A0
Another way to write this is:
Code:
volatile unsigned long *ptr;
ptr = 0x422181A0UL;
*ptr = 1;
Does that make sense now?
As far as the code is concerned, it looks like it is writing to some memory mapped hardware, probably some kind of latch, which is typical of embedded systems.
__________________ Up the Irons
What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home. "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
Down with Sharon Osbourne
Last edited by Scorpions4ever : September 19th, 2012 at 04:45 AM.
Posts: 21
Time spent in forums: 6 h 44 m 11 sec
Reputation Power: 0
Hi Guys,
I know what the instructions are doing and the code Scorpions4ever wrote is exactly how I though it would be written.
What I have never seen is this way of writing this code, is this ANSI-C compliant and if so where would I find more info about it.
Posts: 1,936
Time spent in forums: 1 Month 1 Week 2 h 12 m 42 sec
Reputation Power: 1312
The code
Code:
PB8 = 1;
expands to
Code:
(*((volatile unsigned long *) 0x422181A0)) = 1;
Let's take this apart:
Code:
0x422181A0
That's just an unsigned integer.
Code:
(volatile unsigned long *) 0x422181A0
That's a type cast: the integer 0x422181A0 is treated as a pointer to a volatile unsigned long integer, and that pointer is the result of that expression.
Code:
*((volatile unsigned long *) 0x422181A0)
Here that pointer is dereferenced. Note that a dereferenced pointer is an "lvalue": it can be assigned to, i.e., it can appear on the left-hand side of an assignment expression, speaking of which:
Code:
(*((volatile unsigned long *) 0x422181A0)) = 1;
This stores the value 1 in the block of memory referenced by the pointer.
My point is that if you know what an integer literal is, what a type cast is, what a pointer dereference is, and what the assignment operator is, then you already know this syntax (but you may not know that you know).
Posts: 21
Time spent in forums: 6 h 44 m 11 sec
Reputation Power: 0
Hi Lux Perpetua,
Thank you for that, this was exactly the clarification I was needing. you are right, I already know all the parts, it was just putting it all together. The key is the casting. My other problem is that normally you would create a variable prt or x to be your pointer, but in this case they are not assigning it to anything and that was confusing me. the key, and please correct me if I am wrong, is the #define expression. with this expression you are not assigning or creating a pointer, you are just replacing, in this case, PB8 with the text "(*((volatile unsigned long *) 0x422181A0))" and that's why this works. I am not actually creating a variable called PB8 which happens to be a pointer, I am just saying that where you see PB8 on my program it should actually read "(*((volatile unsigned long *) 0x422181A0))".
Please Guys correct me if I am wrong.
Thank you all so much.
Best Regards
Luis
Posts: 1,936
Time spent in forums: 1 Month 1 Week 2 h 12 m 42 sec
Reputation Power: 1312
Yes, your interpretation there is correct. The #define directive creates a macro. Macros are expanded during preprocessing, which happens before compilation, and macro expansion is literally textual subsitution. What the compiler sees is "(*((volatile unsigned long *) 0x422181A0))"; it never sees "PB8", which is expanded by the preprocessor before the compiler does anything.