设为首页 加入收藏

TOP

C++结构体的字节对齐规则(二)
2014-03-10 12:51:40 来源: 作者: 【 】 浏览:224
Tags:结构 字节 规则

 

  这个例子是一个很典型的例子,可能就是这个例子会让大家误以为,所谓的对齐规则,就是无论对于什么类型的变量,系统都会给它分陪四个字节,从这个例子中可以看到,char 型的napo2的空间也有4个字节。这是因为:先根据上述的第1点,因为该结构体成员中占字节最大的类型是int,所以系统会先随机分配一个能被4整除的地址作为该结构体的首地址,用于存放第一个int变量napo1,因为int 刚好4个字节,所以可以看到char变量napo2的起始地址是napo1地址加上4,而根据上述的第2点,该地址当然也是能够被char变量napo2自身的大小1个字节整除的。关键是看第三个成员int类型的napo3,这里可以看到,napo3的地址是在napo2的首地址的基础上加上4,这是因为napo2只占了1个字节,而根据结构体的字节对齐规则,每个对齐的空间只有4个字节,所以剩下的3个字节已经放不下一个整型的napo3了,而且根据上述的第二点,每个变量的首地址要被自身大小的字节数整除,所以系统会自动偏移3个字节,把int类型的napo3放到了对于napo2地址来说偏移了4个字节的地址处。而char型的napo4当然也只需要一个字节,但是为了空间的对齐(4个字节),所以系统也给char类型分配了4个字节的空间,所以该结构体变量的大小一共是16个字节。用图可表示为:

  |------int--------| 4字节

  |-----char------| 4字节

  |-----int---------| 4字节

  |-----char------| 4字节

  例子2:

  1 #include

  2

  3 struct napo{

  4 char napo1;

  5 char napo2;

  6 int napo3;

  7 int napo4;

  8 }napolin;

  9

  10

  11 int main(void)

  12 {

  13 printf("addr of char napo1:%p\n", &napolin.napo1);

  14 printf("addr of char napo2:%p\n", &napolin.napo2);

  15 printf("addr of int napo3:%p\n", &napolin.napo3);

  16 printf("addr of int napo4:%p\n", &napolin.napo4);

  17 printf("size of struct napolin:%d\n", sizeof(napolin));

  18

  19 return 0;

  20 }

  结果预测:如果系统真的是对于每个不同类型的变量都是分配相同的4个字节,那么这个结构体对象napolin的大小应该也是16各字节

  实验结果:

  addr of char napo1:0x8049720

  addr of char napo2:0x8049721

  addr of int napo3:0x8049724

  addr of int napo4:0x8049728

  size of struct napolin:12

   !!明明完全相同的四个结构提成员,只是顺序发生了变化,为什么创建出来的结构体对象大小居然只有12个字节呢

  同样原理,系统先会随机选择一个能被4整除的地址作为起始地址,因为char的大小是一个字节,所以无论什么地址都能够被它整除,所以char可以放在任何一个位置。所以可以看到在第一个4字节的空间内,两个char型变量napo1和napo2被存在了两个相邻的地址中(20和21),而剩下的两个字节已经放不下一个int类型napo3了,所以napo3的地址被分配为下一个能够被4整除的地址处,也就是24了,而napo4也就很容易理解了。这里加起来也就用了3个4个字节的空间,所以该结构体变量的大小是12个字节。用图描述为:

  |-----------char-----------------| 1

  |-----------char-----------------| 1

  |----------------------------------| 1

  |----------------------------------| 1 总共4字节

  |-------------int----------------- | 4字节

  |-------------int------------------| 4字节

  例子3:

  1 #include

  2

  3 struct napo{

  4 char napo1;

  5 short napo2;

  6 short napo3;

  7 int napo4;

  8 }napolin;

  9

  10

  11 int main(void)

  12 {

  13 printf("addr of char napo1 :%p\n", &napolin.napo1);

  14 printf("addr of short napo2 :%p\n", &napolin.napo2);

  15 printf("addr of short napo3 :%p\n", &napolin.napo3);

  16 printf("addr of int napo4 :%p\n", &napolin.napo4);

  17 printf("size of struct napolin:%d\n", sizeof(napolin));

  18

  19 return 0;

  20 }

  实验结果:

  addr of char napo1 :0x8049730

  addr of short napo2 :0x8049732

  addr of short napo3 :0x8049734

  addr of int napo4 :0x8049738

  size of struct napolin:12

  同样道理,以4个字节作为一个对齐的空间,第一个空间只能放下一个char(1字节)和一个short(两字节),且short的地址要能被2整除,所以看到short类型的napo2的起始地址是32并不是31,而第二个对齐空间只能放下一个2个字节的short而放不下一个int了,所以总共就有三个4字节的对齐空间,所以该结构提变量的大小是12个字节。

  既然有字节对齐这么一回事,当然也就有修改它的方法,下面就介绍一下:

  方法一:在程序的开头,在宏定义的位置加上下面的代码

  #pragma pack(1) //取消字节对齐

  #pragma pack() //恢复字节对齐

  #pragma pack(2) //以2字节对齐

  //#pragma pack(8) //只能缩小不能放大,也就是说通过这种方法,不能使程序按照大于4字节的空间对齐,只能小于或等于4字节的空间对齐

  方法二:在定义结构体的时候如下定义:

  struct ss{

  int a;

  char b;

  int c;

  char d;

  }__attribute__((packed)); //取消字节对齐

  //以8字节对齐 该种方法只能放大不能缩小 ,也就是说通过这种方法,不能使程序按照小于4字节的空间对齐,只能大于4字节的空间对齐

  //__attribute__((aligned(8)));

  Wechat:Shalomlin QQ:373381362

      

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇实现单实例多线程安全API问题 下一篇C++ inline(内联什么时候使..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·HTTPS 详解一:附带 (2025-12-26 02:20:37)
·TCP/IP协议到底在讲 (2025-12-26 02:20:34)
·TCP和UDP在socket编 (2025-12-26 02:20:32)
·有没有适合新手练习 (2025-12-26 01:48:47)
·用清华镜像网怎么下 (2025-12-26 01:48:44)