Home > OS >  Function arguments alignment in C
Function arguments alignment in C

Time:05-24

The array in procedure breaking procedure arguments alignment. Having a following code:

void _func(unsigned long cnt, int* adr, ...){
    char a[1];
    printf("cnt: %p, adr: %p\n", &cnt, &adr);
}

int main(void){
    _func(0, (int*)1, 2, 3, 4, 5);
    return 0;
}

... that is compiled with

gcc -m32 -O0 main.c

and it outputs this:

cnt: 0xff911960, adr: 0xff91193c

which is 36 (0x24) bytes difference. And the question is why it is? Isn't is should be sizeof(cnt)?

But if I remove char a[1] or add -O2 flag, the difference would be 4 bytes (as usual).

What causes this behavior?

PS: on compiler explorer website, the offset is 4 bytes all the time.

CodePudding user response:

&cnt and &adr are addresses of parameters. Parameters are variables local to the function that are initialized to the argument values passed by the caller. The compiler is not required to use the same space for parameters that is used to pass the arguments.

When an argument is passed on the stack, a compiler might or might not reuse its stack space for the parameter. When an argument is passed in a processor register and an address is needed for it, as because a program takes the address and prints it, then the compiler has to reserve space for the parameter on the stack, copy the value from the register to the stack space (as with a store instruction), and use the address of the stack space.

When the compiler is laying out stack space for this, it does not need to care that cnt and adr are consecutive parameters. It can organize data about all the stack space it needs—for parameters, for local variables, for the return address, for its own purposes, whatever—and then just assign stack space for those things in any order. So you should not expect there to be any close relationship between the addresses of cnt and adr.

(For functions with variable arguments, the compiler needs someway to implement the variable argument list features. This usually involves having the variable arguments consecutive in memory after the last fixed argument, which would be adr in the example. This does not impose any relationship between cnt and adr.)

  • Related