标题:本来面试前应该看的:字节对齐, #pragma pack 出处:Felix021 时间:Mon, 18 May 2009 16:05:25 +0000 作者:felix021 地址:https://www.felix021.com/blog/read.php?1600 内容: 网上可以搜到很多相关的资料,这里不具体说了, 大致就是,定义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 #include 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; } Generated by Bo-blog 2.1.0