Reputation: 2691
I am doing some experiments to see how C allocates variables on the stack. I am getting some odd behavior with the following code. C appears to be growing the stack downward, so in the following example, the char c is allocated in the byte immediately before the short s. I then create an int pointer bigRandP
and point it at the same location occupied by c, so the "int" it sees overlaps with the space on the stack occupied by s. I then try to assign something to the location referenced by the int pointer.
unsigned short nameSum = 0;
unsigned char smallRand = 0;
unsigned int* bigRandP;
//The "int" pointed to by iP should overlap s
bigRandP = (unsigned int*)(&smallRand);
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
*bigRandP = 0;
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
0028FF1A 0028FF19 0028FF19
0 0 419430400
0028FF1A 0028FF19 0028FF00
0 0 4210788
The printed results are interesting. Not only does the assignment fail (the int pointed to by bigRandP is not set to 0), the int pointer itself is silently relocated to point somewhere else further down the stack. What is going on? Is this the C compiler's way of keeping me from overwriting other variables with overlapping pointers?
Upvotes: 0
Views: 194
Reputation: 263497
bigRandP
is a pointer to unsigned int
.
You pointed it to an unsigned char
object, then you modified the unsigned int
object that bigRandP
points to.
Apparently smallRand
and bigRandP
are stored close to each other in memory. By trying to modify sizeof (unsigned int)
bytes of a 1-byte object, you clobbered part of the pointer object itself.
Bottom line: Your program's behavior is undefined.
Also, though this probably isn't related to the behavior you're seeing, the %p
format requires a void*
argument. If you want to print some other type of pointer, you should convert it to void*
:
printf("%p %p %p\n", (void*)&nameSum, (void*)&smallRand, (void*)bigRandP);
It's likely to "work" with or without the casts on systems where all pointers have the same representation, but the version with the casts is more correct on all systems.
Upvotes: 4