May 18

本来面试前应该看的:字节对齐, #pragma pack 不指定

felix021 @ 2009-5-18 16:05 [IT » 程序设计] 评论(1) , 引用(0) , 阅读(9104) | Via 本站原创 | |
网上可以搜到很多相关的资料,这里不具体说了,
大致就是,定义struct/class的时候 编译器会把其中的每个成员的存储位置对齐
对齐原则一般是和该成员大小一致,比如int的就从%4=0的地址开始存储,多余的空间就编译器随便填充了。
然后struct还要填充,直到整个struct的大小是最大成员大小的倍数(VC6.0)——为什么呢?
Felix觉得这样是为了保证连续存储的时候下一个struct的最大成员也是对齐的。
此外,编译器还会对struct的存储地址进行对齐。

我实际测试了一下,我发现32bit的gcc在对struct进行填充的时候
如果某成员的大小大于4Bytes(long long, double)的时候,实际上是以4字节对齐的。

如果在程序中指定了
#pragma pack(n)
那么对齐的时候就会把元素的大小和n进行比较,取较小的那个来对齐。

此外:
#pragma pack(push)
#program pack(pop)
可以成对使用,用来保存(push)当前的n和取出(pop)之前的n——当然,这是在编译过程中处理的。

下面是我的一段测试程序:
#include <stdio.h>
#include <string.h>

struct ta{
    unsigned char a; // 1 Byte
    unsigned long long b; // 8 Byte
    unsigned short c; // 1 Byte
};

#pragma pack(2)
struct tb{
    unsigned char a; // 1 Byte
    unsigned long long b; // 8 Byte
    unsigned short c; // 1 Byte
};

void dump(void *t, int size){
    printf("---- @%x size = %2d ----\n", (int)t, size);
    for (int i = 0; i < size; ++i){
        printf("%2d: %x\n", i, *((char*)t+i));
    }
    printf("-------------------\n");
}

int main(){
    ta a;
    memset(&a, 0, sizeof(ta));
    a.a = 0xff;
    a.b = 0xffffffffffffffffull;
    a.c = 0xffff;
    dump(&a, sizeof(ta));

    tb b;
    memset(&b, 0, sizeof(tb));
    b.a = 0xff;
    b.b = 0xffffffffffffffffull;
    b.c = 0xffff;
    dump(&b, sizeof(tb));
    return 0;
}




欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
非人
2009-5-18 20:08
呵呵 我倒是准备这个了 结果那人没问 汗- -
felix021 回复于 2009-5-19 13:56
。。。
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]