I have the following program. I wonder why it outputs -4 on the following 64 bit machine? Which of my assumptions went wrong ?
[Linux ubuntu 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC
2012 x86_64 x86_64 x86_64 GNU/Linux]
-
In the above machine and gcc compiler, by default b should be pushed first and a second.
The stack grows downwards. So b should have higher address and a have lower address. So result should be positive. But I got -4. Can anybody explain this ? -
The arguments are two chars occupying 2 bytes in the stack frame. But I saw the difference as 4 where as I am expecting 1. Even if somebody says it is because of alignment, then I am wondering a structure with 2 chars is not aligned at 4 bytes.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void CompareAddress(char a, char b) { printf("Differs=%ld\n", (intptr_t )&b - (intptr_t )&a); } int main() { CompareAddress('a','b'); return 0; } /* Differs= -4 */
The best way to answer these sort of questions (about behaviour of a specific compiler on a specific platform) is to look at the assembler. You can get
gccto dump its assembler by passing the-Sflag (and the-fverbose-asmflag is nice too). Runninggives a
file.sthat looks a little like (I’ve removed all the irrelevant bits, and the bits in parenthesis are my notes):(This question explains nicely what
[re]bpand[re]spare.)The reason the difference is negative is the stack grows downward: i.e. if you push two things onto the stack, the one you push first will have a larger address, and
ais pushed beforeb.The reason it is
-4rather than-1is the compiler has decided that aligning the arguments to 4 byte boundaries is “better”, probably because a 32 bit/64 bit CPU deals with 4 bytes at time better than it handles single bytes.(Also, looking at the assembler shows the effect that
-mpreferred-stack-boundaryhas: it essentially means that memory on the stack is allocated in different sized chunks.)