开发者

Basic data alignment question

I've been playing around to see how my computer works under the hood. What I'm interested in is seeing is what happens on the stack inside a function. To do this I've written the following toy program:

#include <stdio.h>

void __cdecl Test1(char a, unsigned long long b, char c)
{
    char c1;
    unsigned long long b1;
    char a1;
    c1 = 'b';
    b1 = 4;
    a1 = 'r';
    printf("%d %d - %d - %d %d Total: %d\n", 
        (long)&b1 - (long)&a1, (long)&c1 - (long)&b1,
        (long)&a - (long)&c1,
        (long)&b - (long)&a, (long)&c - (long)&b,
        (long)&c - (long)&a1
        );
};

struct TestStruct
{
    char a;
    unsigned long long b;
    char c;
};

void __cdecl Test2(char a, unsigned long long b, char c)
{
    TestStruct locals;
    locals.a = 'b';
    locals.b = 4;
    locals.c = 'r';
    printf("%d %d - %d - %d %d Total: %d\n", 
        (long)&locals.b - (long)&locals.a, (long)&locals.c - (long)&locals.b,
        (long)&a - (long)&locals.c,
        (long)&b - (long)&a, (long)&c - (long)&b,
        (long)&c - (long)&locals.a
        );
};

int main()
{
    Test1('f', 0, 'o');
    Test2('f', 0, 'o');
    return 0;
}

And this spits out the following:

9 19 - 13 - 4 8 Total: 53

8 8 - 24 - 4 8 Total: 52

The function args are well 开发者_如何学Pythonbehaved but as the calling convention is specified, I'd expect this. But the local variables are a bit wonky. My question is, why wouldn't these be the same? The second call seems to produce a more compact and better aligned stack.

Looking at the ASM is unenlightening (at least to me), as the variable addresses are still aliased there. So I guess this is really a question about the assembler itself allocates the stack to local variables.

I realise that any specific answer is likely to be platform specific. I'm more interested in a general explanation unless this quirk really is platform specific. For the record though, I'm compiling with VS2010 on a 64bit Intel machine.


Memory layout of POD structs is pretty much specified and guaranteed by language rules + type alignment/size requirements on your platform.

Implementation has free hands with the local variables and function parameters. It is most likely that it puts some of these into stack only because you use unary & operator to take their addresses.

When local variable is not used then compiler may optimize out its initialization. When local simple variable is used very intensively then compiler may use register for it. When local variable is used only once then compiler may use its value directly in place of usage.

If you want function parameters layout to be better specified/guaranteed then you have to use extern "C" linkage.


In Test1, you define a bunch of local variables. The compiler is not forced to pack them together, or in the same order that you declare them.

In Test2, you define an struct, and the compiler pad data using http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜