来个明白人给解释一下对齐(pragma pack)吧

sdu_hanson 2014-07-14 04:42:46
我这有个结构体
#pragma pack(1) //1字节对齐
struct
{
unsigned Info:10;
unsigned Func:8;
unsigned SA:4;
unsigned DA:4;
unsigned RES:2;
unsigned p:1;
}ID;

还有个字符数组
BYTE tempBuf[4];
tempBuf[0] =1;
tempBuf[1] =1;
tempBuf[2] =1;
tempBuf[3] =2;

然后用函数memcpy(&CanData.ID,tempBuf,4);赋值

这时候得到结果是
ID.Info = 257;
ID.Func=64;
ID.SA =0;
ID.DA = 8;
ID.RES = 0;
ID.P = 0;

这个是怎么对齐的啊。。。
ID.Info =257看起来是对应了tempBuf的前两个字节,
ID.Func = 64是怎么得来的呢,
实在想不通了。

麻烦明白人给解释一下吧
...全文
282 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
Cnwanglin 2014-07-15
  • 打赏
  • 举报
回复
我都拿颜色标记出来了...难道不明显吗
Cnwanglin 2014-07-15
  • 打赏
  • 举报
回复
是的
引用 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]
sdu_hanson 2014-07-15
  • 打赏
  • 举报
回复
引用 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 是这样吗?
Cnwanglin 2014-07-15
  • 打赏
  • 举报
回复
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 依次类推
sdu_hanson 2014-07-15
  • 打赏
  • 举报
回复
引用 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个二进制位,都是从下往上取是吧?
sdu_hanson 2014-07-15
  • 打赏
  • 举报
回复
引用 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才对啊?
SuperLiusw 2014-07-15
  • 打赏
  • 举报
回复
c++ primer plus中有详细解释:位域的问题
sdu_hanson 2014-07-15
  • 打赏
  • 举报
回复
差不多搞明白了,谢谢大家
赵4老师 2014-07-14
  • 打赏
  • 举报
回复
#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

707wk 2014-07-14
  • 打赏
  • 举报
回复
引用 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
nice_cxf 2014-07-14
  • 打赏
  • 举报
回复
笔误,DA:4,结果1000,值为8 p:1; 对应tempBuf[3]第4字节,为0
nice_cxf 2014-07-14
  • 打赏
  • 举报
回复
按一字节对齐,跟字节对齐无关 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
sdu_hanson 2014-07-14
  • 打赏
  • 举报
回复
引用 7 楼 aqtata 的回复:
struct
 {
 unsigned Info:10;      
 unsigned Func:8;      
 unsigned SA:4; 
 unsigned DA:4; 
 unsigned RES:2;   
 unsigned p:1;                     
 }ID;
29位也能编译通过吗?
能啊
一如当初 2014-07-14
  • 打赏
  • 举报
回复
struct
 {
 unsigned Info:10;      
 unsigned Func:8;      
 unsigned SA:4; 
 unsigned DA:4; 
 unsigned RES:2;   
 unsigned p:1;                     
 }ID;
29位也能编译通过吗?
sdu_hanson 2014-07-14
  • 打赏
  • 举报
回复
引用 5 楼 zhao4zhong1 的回复:
位域
谢谢,我去看看~~~~~
赵4老师 2014-07-14
  • 打赏
  • 举报
回复
位域
JasonCharlesBourne 2014-07-14
  • 打赏
  • 举报
回复
引用 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字节对齐
sdu_hanson 2014-07-14
  • 打赏
  • 举报
回复
引用 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字节。
这个我能看懂,但是套不上啊
Cnwanglin 2014-07-14
  • 打赏
  • 举报
回复
在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字节。
赵4老师 2014-07-14
  • 打赏
  • 举报
回复
位域。 仅供参考
#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)

69,368

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧