user-0 提问: 来个明白人给解释一下对齐(pragma pack)吧

回复:
user: user-1
content: 我都拿颜色标记出来了...难道不明显吗

user: user-1
content: 是的  引用 16 楼 sdu_hanson 的回复:[quote=引用 15 楼 Cnwanglin 的回复:] 1000 0000 1000 0000 1000 0000 0100 0000 tempBuf[0] =1000 0000; tempBuf[1] =1000 0000; tempBuf[2] =1000 0000; tempBuf[3] =0100 0000;  从上到下开始数 struct { unsigned	Info:10;       unsigned	Func:8;       unsigned	SA:4;	 unsigned	DA:4;	 unsigned	RES:2;	    unsigned	p:1;                      }ID;  info 10位 1000 0000 10  输出的时候颠倒位置 01 0000 0001 = 257 func 8 位  0000 0010 输出0100 0000 = 64 依次类推 恩，比如1，在内存中存储顺序是 1 0 0 0 0 0 0 0 而不是 0 0 0 0 0 0 0 1  是这样吗？[/quote]

user: user-0
content: 引用 15 楼 Cnwanglin 的回复:1000 0000 1000 0000 1000 0000 0100 0000 tempBuf[0] =1000 0000; tempBuf[1] =1000 0000; tempBuf[2] =1000 0000; tempBuf[3] =0100 0000;  从上到下开始数 struct { unsigned	Info:10;       unsigned	Func:8;       unsigned	SA:4;	 unsigned	DA:4;	 unsigned	RES:2;	    unsigned	p:1;                      }ID;  info 10位 1000 0000 10  输出的时候颠倒位置 01 0000 0001 = 257 func 8 位  0000 0010 输出0100 0000 = 64 依次类推 恩，比如1，在内存中存储顺序是 1 0 0 0 0 0 0 0 而不是 0 0 0 0 0 0 0 1  是这样吗？

user: user-1
content: 1000 0000 1000 0000 1000 0000 0100 0000 tempBuf[0] =1000 0000; tempBuf[1] =1000 0000; tempBuf[2] =1000 0000; tempBuf[3] =0100 0000;  从上到下开始数 struct { unsigned	Info:10;       unsigned	Func:8;       unsigned	SA:4;	 unsigned	DA:4;	 unsigned	RES:2;	    unsigned	p:1;                      }ID;  info 10位 1000 0000 10  输出的时候颠倒位置 01 0000 0001 = 257 func 8 位  0000 0010 输出0100 0000 = 64 依次类推

user: user-0
content: 引用 9 楼 nice_cxf 的回复:按一字节对齐，跟字节对齐无关 Info：10,对应tempBuf[0]的8字节的01和tempBuf[1]的01字节01，二进制为0100000001：257 Func:8，对应tempBuf[1]的高6字节0和tempBuf[2]的低两个字节01，二进制为0100000，10进制为64 SA:4，对应tempBuf[2]的2-5字节，二进制为0000	 DA:4，	对应tempBuf[2]的67字节和tempBuf[3]的第01字节，为1000，结果为4 RES:2，	对应tempBuf[3]第23字节，为00    p:1; 对应tempBuf[3]第4字节，为00 你好  1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0  你的意思是info是10个二进制位，都是从下往上取是吧？

user: user-0
content: 引用 9 楼 nice_cxf 的回复:按一字节对齐，跟字节对齐无关 Info：10,对应tempBuf[0]的8字节的01和tempBuf[1]的01字节01，二进制为0100000001：257 Func:8，对应tempBuf[1]的高6字节0和tempBuf[2]的低两个字节01，二进制为0100000，10进制为64 SA:4，对应tempBuf[2]的2-5字节，二进制为0000	 DA:4，	对应tempBuf[2]的67字节和tempBuf[3]的第01字节，为1000，结果为4 RES:2，	对应tempBuf[3]第23字节，为00    p:1; 对应tempBuf[3]第4字节，为00 你好，还是不大明白 Info：10,对应tempBuf[0]的8字节的01和tempBuf[1]的01字节01，二进制为0100000001：257 为什么会是对应tempbuf【1】的01两位呢？ 00000001000000010000000100000010 我感觉应该是前十个二进制位0000000100才对啊？

user: user-2
content: c++ primer plus中有详细解释：位域的问题

user: user-0
content: 差不多搞明白了，谢谢大家

user: user-3
content: #include <stdio.h> #pragma pack(push,1) union U {     unsigned char byte;     struct BF {         unsigned int b0:1;//a         unsigned int b1:1;//b         unsigned int b2:1;//c     } bf; } u; #pragma pack(pop) unsigned char bt; int a,b,c; int main() {     for (bt=0;bt<8;bt++) {         u.byte=(unsigned char)bt;         a=u.bf.b0;         b=u.bf.b1;         c=u.bf.b2;         printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);     }     for (c=0;c<2;c++)     for (b=0;b<2;b++)     for (a=0;a<2;a++) {         u.bf.b0=a;         u.bf.b1=b;         u.bf.b2=c;         bt=u.byte;         printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);     }     return 0; } //byte 0x00 -- c:0 b:0 a:0 //byte 0x01 -- c:0 b:0 a:1 //byte 0x02 -- c:0 b:1 a:0 //byte 0x03 -- c:0 b:1 a:1 //byte 0x04 -- c:1 b:0 a:0 //byte 0x05 -- c:1 b:0 a:1 //byte 0x06 -- c:1 b:1 a:0 //byte 0x07 -- c:1 b:1 a:1 //c:0 b:0 a:0 -- byte 0x00 //c:0 b:0 a:1 -- byte 0x01 //c:0 b:1 a:0 -- byte 0x02 //c:0 b:1 a:1 -- byte 0x03 //c:1 b:0 a:0 -- byte 0x04 //c:1 b:0 a:1 -- byte 0x05 //c:1 b:1 a:0 -- byte 0x06 //c:1 b:1 a:1 -- byte 0x07

user: user-4
content: 引用 2 楼 Cnwanglin 的回复:在C语言中，结构是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如数组、结构、联合等）的数据单元。在结构中，编译器为结构的每个成员按其自然对界（alignment）条件分配空间。(所谓自然对界条件是指有些CPU要求数据存放的时候要对齐，就是起始地址必须是所占字节数的整数倍。RISC   CPU就有这种要求。如果在PowerPC的系统上用这样一个结构：    struct s {  Char a;  long b;  };     在内存里就会看到：（字母表示这个字节属于谁） a   0   0   0    b   b   b   b    由于b需要对齐，所以a和b之间就有了一个3字节的pad。要是取sizeof(struct   s)，就会看到是8。这种对齐在RISC   CPU上是必须的，否则会出错.     在x86上面则没有这种必须对齐的要求，a和b之间可以不需要pad。但是你并不能确定他们之间到底有没有这个pad，这个和编译器有关系。因为数据对齐的时候访问效率最高，所以有的编译器进行了优化，就是在x86上数据照样也是对齐的。比如gcc，用gcc得到的sizeof(struct   s)就是8，但是如果用Turbo   C，就会看到是5。 “自然对界条件”对齐条件，不是说变量的起始地址必须是其所占字节数的整数倍   ！    注意这里的起始地址   是相对地址   ！   从   0   开始计算的   ～) 各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。 例如，下面的结构各成员空间分配情况： struct test  {      char x1;      short x2;      float x3;      char x4; }; 结构的第一个成员x1，其偏移地址为0，占据了第1个字节。第二个成员x2为short类型，其起始地址必须2字节对界，因此，编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上，在它们前面不需要额外的填充字节。在test结构中，成员x3要求4字节对界，是该结构所有成员中要求的最大对界单元，因而test结构的自然对界条件为4字节，编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。+1

user: user-5
content: 笔误，DA:4，结果1000，值为8 p:1; 对应tempBuf[3]第4字节，为0

user: user-5
content: 按一字节对齐，跟字节对齐无关 Info：10,对应tempBuf[0]的8字节的01和tempBuf[1]的01字节01，二进制为0100000001：257 Func:8，对应tempBuf[1]的高6字节0和tempBuf[2]的低两个字节01，二进制为0100000，10进制为64 SA:4，对应tempBuf[2]的2-5字节，二进制为0000	 DA:4，	对应tempBuf[2]的67字节和tempBuf[3]的第01字节，为1000，结果为4 RES:2，	对应tempBuf[3]第23字节，为00    p:1; 对应tempBuf[3]第4字节，为00

user: user-0
content: 引用 7 楼 aqtata 的回复:struct  {  unsigned Info:10;        unsigned Func:8;        unsigned SA:4;   unsigned DA:4;   unsigned RES:2;     unsigned p:1;                       }ID;  29位也能编译通过吗？  能啊

user: user-6
content: struct  {  unsigned Info:10;        unsigned Func:8;        unsigned SA:4;   unsigned DA:4;   unsigned RES:2;     unsigned p:1;                       }ID;  29位也能编译通过吗？

user: user-0
content: 引用 5 楼 zhao4zhong1 的回复:位域 谢谢，我去看看~~~~~

user: user-3
content: 位域

user: user-7
content: 引用 2 楼 Cnwanglin 的回复:在C语言中，结构是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如数组、结构、联合等）的数据单元。在结构中，编译器为结构的每个成员按其自然对界（alignment）条件分配空间。(所谓自然对界条件是指有些CPU要求数据存放的时候要对齐，就是起始地址必须是所占字节数的整数倍。RISC   CPU就有这种要求。如果在PowerPC的系统上用这样一个结构：    struct s {  Char a;  long b;  };     在内存里就会看到：（字母表示这个字节属于谁） a   0   0   0    b   b   b   b    由于b需要对齐，所以a和b之间就有了一个3字节的pad。要是取sizeof(struct   s)，就会看到是8。这种对齐在RISC   CPU上是必须的，否则会出错.     在x86上面则没有这种必须对齐的要求，a和b之间可以不需要pad。但是你并不能确定他们之间到底有没有这个pad，这个和编译器有关系。因为数据对齐的时候访问效率最高，所以有的编译器进行了优化，就是在x86上数据照样也是对齐的。比如gcc，用gcc得到的sizeof(struct   s)就是8，但是如果用Turbo   C，就会看到是5。 “自然对界条件”对齐条件，不是说变量的起始地址必须是其所占字节数的整数倍   ！    注意这里的起始地址   是相对地址   ！   从   0   开始计算的   ～) 各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。 例如，下面的结构各成员空间分配情况： struct test  {      char x1;      short x2;      float x3;      char x4; }; 结构的第一个成员x1，其偏移地址为0，占据了第1个字节。第二个成员x2为short类型，其起始地址必须2字节对界，因此，编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上，在它们前面不需要额外的填充字节。在test结构中，成员x3要求4字节对界，是该结构所有成员中要求的最大对界单元，因而test结构的自然对界条件为4字节，编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。 你这不说的废话么，人家明明写了按1字节对齐

user: user-0
content: 引用 2 楼 Cnwanglin 的回复:在C语言中，结构是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如数组、结构、联合等）的数据单元。在结构中，编译器为结构的每个成员按其自然对界（alignment）条件分配空间。(所谓自然对界条件是指有些CPU要求数据存放的时候要对齐，就是起始地址必须是所占字节数的整数倍。RISC   CPU就有这种要求。如果在PowerPC的系统上用这样一个结构：    struct s {  Char a;  long b;  };     在内存里就会看到：（字母表示这个字节属于谁） a   0   0   0    b   b   b   b    由于b需要对齐，所以a和b之间就有了一个3字节的pad。要是取sizeof(struct   s)，就会看到是8。这种对齐在RISC   CPU上是必须的，否则会出错.     在x86上面则没有这种必须对齐的要求，a和b之间可以不需要pad。但是你并不能确定他们之间到底有没有这个pad，这个和编译器有关系。因为数据对齐的时候访问效率最高，所以有的编译器进行了优化，就是在x86上数据照样也是对齐的。比如gcc，用gcc得到的sizeof(struct   s)就是8，但是如果用Turbo   C，就会看到是5。 “自然对界条件”对齐条件，不是说变量的起始地址必须是其所占字节数的整数倍   ！    注意这里的起始地址   是相对地址   ！   从   0   开始计算的   ～) 各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。 例如，下面的结构各成员空间分配情况： struct test  {      char x1;      short x2;      float x3;      char x4; }; 结构的第一个成员x1，其偏移地址为0，占据了第1个字节。第二个成员x2为short类型，其起始地址必须2字节对界，因此，编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上，在它们前面不需要额外的填充字节。在test结构中，成员x3要求4字节对界，是该结构所有成员中要求的最大对界单元，因而test结构的自然对界条件为4字节，编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。 这个我能看懂，但是套不上啊

user: user-1
content: 在C语言中，结构是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如数组、结构、联合等）的数据单元。在结构中，编译器为结构的每个成员按其自然对界（alignment）条件分配空间。(所谓自然对界条件是指有些CPU要求数据存放的时候要对齐，就是起始地址必须是所占字节数的整数倍。RISC   CPU就有这种要求。如果在PowerPC的系统上用这样一个结构：    struct s {  Char a;  long b;  };     在内存里就会看到：（字母表示这个字节属于谁） a   0   0   0    b   b   b   b    由于b需要对齐，所以a和b之间就有了一个3字节的pad。要是取sizeof(struct   s)，就会看到是8。这种对齐在RISC   CPU上是必须的，否则会出错.     在x86上面则没有这种必须对齐的要求，a和b之间可以不需要pad。但是你并不能确定他们之间到底有没有这个pad，这个和编译器有关系。因为数据对齐的时候访问效率最高，所以有的编译器进行了优化，就是在x86上数据照样也是对齐的。比如gcc，用gcc得到的sizeof(struct   s)就是8，但是如果用Turbo   C，就会看到是5。 “自然对界条件”对齐条件，不是说变量的起始地址必须是其所占字节数的整数倍   ！    注意这里的起始地址   是相对地址   ！   从   0   开始计算的   ～) 各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。 例如，下面的结构各成员空间分配情况： struct test  {      char x1;      short x2;      float x3;      char x4; }; 结构的第一个成员x1，其偏移地址为0，占据了第1个字节。第二个成员x2为short类型，其起始地址必须2字节对界，因此，编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上，在它们前面不需要额外的填充字节。在test结构中，成员x3要求4字节对界，是该结构所有成员中要求的最大对界单元，因而test结构的自然对界条件为4字节，编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。

user: user-3
content: 位域。 仅供参考#include <stdio.h> #include <stdlib.h> char buf[17]; union U {   unsigned short int aa;   struct S {     unsigned int bb:7;//(bit 0-6)     unsigned int cc:6;//(bit 7-12)     unsigned int dd:3;//(bit 13-15)   } s; } u; void main() {                 //bbbbbbbbbbbbbbbb                 //iiiiiiiiiiiiiiii                 //tttttttttttttttt                 //111111                 //5432109876543210                 //::::::::::::::::     u.aa=0xE07F;//1110000001111111     printf("bb==%d,cc==%d,dd==%d\n",u.s.bb,u.s.cc,u.s.dd);     u.s.bb=0x41;     u.s.cc=0x21;//dddccccccbbbbbbb     u.s.dd=5;   //1011000011000001     printf("aa==0x%04X==%016s(2)\n",u.aa,itoa(u.aa,buf,2)); } //bb==127,cc==0,dd==7 //aa==0xB0C1==1011000011000001(2)