c++字节对齐

规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该“变量的类型”或者指定对齐系数所占用的字节数的倍数,当变量类型和指定系数不同时,取小的。整个结构大小按照以上对齐计算,但必须是最大类型大小或者指定对齐系数的整数倍,也就是最后一个成员变量要圆整,当最大类型大小和指定对齐系数不一致的情况,取小的。当成员变量本身是结构体的时候,不能用整个struct大小计算起始地址,而应该用结构体中最大类型大小代替整个struct变量计算起始地址。


如:

typedef struct {  
        char x;  
        int y[5];  
        char z;  
    }struct_m; //28

    typedef struct {  
        char x;  
        double y[5];  
        char z;  
    }struct_n;  //56

    typedef struct{  
        char x;  
        struct_m f;  //起始地址必须为最大类型-整形的整数倍,即int的整数倍,4
        char y;  
        struct_n g;  //起始地址必须为struct_n中double的整数倍,40
    }struct_o;

一.基本数据的长度(32位windows平台)

char:1(有符号无符号同)
short:2(有符号无符号同)
int:4(有符号无符号同)
long:4(有符号无符号同)
float:4

double:8

二.对齐的作用和原因:

各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。

三.一些常见的和需要注意的sizeof

char* a= "abc";     //sizeof(a)=4

==============================================

char b[100];   //sizeof(b)=100;

==============================================

char* c=(char*)malloc(100); //sizeof(c)=100

==============================================

char d[] = "abc"; //sizeof(d)=4

==============================================

int e[100]; //求数组的元素个数int c2 = sizeof( e ) / sizeof( e[0] ); // 总长度/第一个元素的长度

==============================================

void foo3(char f[3])
{
    int c3 = sizeof( f); // c3 =4
}

==============================================

void foo4(char g[])
{
    int c4 = sizeof( g); // c4 =4
}

==============================================

int a = 1, b =2; 执行sizeof (a = b)

之后为什么a=1, 而不是2. 为什么没有执行赋值操作? (淘宝笔试题)

    (1)sizeof (type-name) 是求变量类型的大小 ,在编译期执行 ,因为sizeof 是在编译期内执行而不是在运行期 所以 sizeof  (a  =  b)  是不会运行a  =  b 这个操作的。

    (2)sizeof是一个运算符而不是一个函数。 编译器会查符号表求出值大小,而不会执行里面的表达式

    (3)sizeof  是如何来看待  a  =  b的?

        sizeof 是按照类型计算字节的,与值无关。 在编译器中,上句等价于  sizeof( int = int ),

        结果按照“左值”计算字节数

        你可以试试

        int a=1;

        double b=2.0;

        cout < <sizeof(a=b);    //等价于  sizeof(int= double)  自动cast

        cout < <sizeof(b=a);    //等价于  sizeof(double = int)

        一个结果是 4,一个是8

   (4)sizeof(1)  1  是int类型 所以4 

        sizeof(1.1) 1.1 为double 所以8 

        当然这个根据机器不同结果也不一样

四.结构体和类的规则

1.数据类型自身的对齐值:
  对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
3.指定对齐值:#pragma pack (value)时的指定对齐值value。
4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

上面包含两层意思:

一是结构体(类)里面的成员地址要按照自身的大小对齐,也就是addressof(struct.number)%sizeof(struct.number)=0;对于结构体内部为复杂类型的成员(例如结构体,数组等),其地址以其自身的最大成员大小对其。

二是整个结构体(类)要按照成员中自身对齐值最大(N)的那个值进行对齐,也就是sizeof(struct)%N=0。这里的N为最大的基本类型,对于复杂类型看的是其中最大成员大小,而不是复杂类型的大小。

五.例子

  1. #include "stdio.h"  
  2. #include "stddef.h"  
  3. //#define offsetof(s,m) (size_t)&(((s *)0)->m)  
  4. typedef struct {  
  5.     char a;     // 1 byte  
  6.     int b;      // 4 bytes  
  7.     short c;    // 2 bytes  
  8.     char d;     // 1 byte  
  9. } struct_a;  
  10. typedef struct  {  
  11.     char a;            // 1 byte  
  12.     char _pad0[3];     // padding to put 'b' on 4-byte boundary  
  13.     int b;            // 4 bytes  
  14.     short c;          // 2 bytes  
  15.     char d;           // 1 byte  
  16.     char _pad1[1];    // padding to make sizeof(x_) multiple of 4  
  17. }struct_b;  
  18.   
  19. //struct_x强制 模1 对齐.  
  20. # pragma pack (1)  
  21. typedef struct  
  22. {  
  23.     char a;    // 1 byte  
  24.     int b;     // 4 bytes  
  25.     short c;   // 2 bytes  
  26. }  struct_c;  
  27. # pragma pack ()  
  28.   
  29. //struct_x被强制 模2 对齐.  
  30. # pragma pack (2)  
  31. typedef struct  
  32. {  
  33.     char a;    // 1 byte  
  34.     int b;     // 4 bytes  
  35.     short c;   // 2 bytes  
  36. }  struct_d;  
  37. # pragma pack ()  
  38. //struct_x被强制 模8对齐.  
  39. # pragma pack (8)  
  40. typedef struct  
  41. {  
  42.     char a;    // 1 byte  
  43.     int b;     // 4 bytes  
  44.     short c;   // 2 bytes  
  45. }  struct_e;  
  46. # pragma pack ()  
  47. typedef struct  
  48. {  
  49.     char a;  
  50.     short b;  
  51.     char c;  
  52. }struct_f;  
  53. typedef struct  
  54. {  
  55.     char a;  
  56.     char c;  
  57.     short b;  
  58. }struct_g;  
  59. typedef struct  
  60. {  
  61.     char b;  
  62.     int a;  
  63.     short c;  
  64. }struct_h;  
  65. typedef struct{   
  66.     unsigned char incon: 8; /*incon占用低字节的0~7共8位*/   
  67.     unsigned char txcolor: 4;/*txcolor占用高字节的0~3位共4位*/   
  68.     unsigned char bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/   
  69.     unsigned char blink: 1; /*blink占用高字节的第7位*/   
  70. }struct_i;    
  71. typedef struct{  //整个结构体要以2(sizeof(unsigned short))对齐  
  72.     unsigned short   incon: 8;   
  73.     unsigned short   txcolor: 4;  
  74.     unsigned short   bgcolor: 3;  
  75.     unsigned short   blink: 1;  
  76. }struct_j;    
  77. typedef struct//整个结构体要以4(sizeof(unsigned int))对齐  
  78.     unsigned int   incon: 8;   
  79.     unsigned int   txcolor: 4;  
  80.     unsigned int   bgcolor: 3;  
  81.     unsigned int  blink: 1;  
  82. }struct_k;    
  83. typedef struct//整个结构体要以4(sizeof(unsigned int))对齐  
  84.     unsigned   incon: 8;   
  85.     unsigned   txcolor: 4;  
  86.     unsigned   bgcolor: 3;  
  87.     unsigned   blink: 1;  
  88. }struct_l;    
  89. typedef struct {  
  90.     char x;  
  91.     int y[5];  
  92.     char z;  
  93. }struct_m;  
  94. typedef struct {  
  95.     char x;  
  96.     double y[5];  
  97.     char z;  
  98. }struct_n;  
  99. typedef struct{  
  100.     char x;  
  101.     struct_m f;  
  102.     char y;  
  103.     struct_n g;  
  104. }struct_o;  
  105.   
  106. class CLASS_A{  
  107.     char x;  
  108.     void func();  
  109. };  
  110. class CLASS_B{  
  111.     char x;  
  112.     virtual void func();  
  113. };  
  114. class CLASS_C{  
  115.     char x;  
  116.     char y;  
  117.     virtual void func();  
  118. };  
  119. class CLASS_D{  
  120.     char x;  
  121.     char* z;  
  122.     char y;  
  123.     virtual void func();  
  124. };  
  125. class CLASS_E{  
  126.     char x;  
  127.     CLASS_A a;  
  128.     void func();  
  129. };  
  130. class CLASS_F{  
  131.     char x;  
  132.     int y;  
  133. };  
  134.   
  135. class CLASS_G{  
  136.     char x;  
  137.     CLASS_F f;  
  138.     void func();  
  139. };  
  140. class CLASS_H{  
  141.     char x;  
  142.     CLASS_F* f;  
  143.     void func();  
  144. };  
  145.   
  146. class CLASS_I{  
  147.     char x;  
  148.     virtual void func();  
  149.     virtual void func1();  
  150. };  
  151.   
  152. #define NAMEOF(x) #x  
  153. #define PRINT_SIZEOF(x) do{printf("sizeof(%s)=%d/n",NAMEOF(x),sizeof(x));}while(0)  
  154. int main(){  
  155.     PRINT_SIZEOF(struct_a);  
  156.     PRINT_SIZEOF(struct_b);  
  157.     PRINT_SIZEOF(struct_c);  
  158.     PRINT_SIZEOF(struct_d);  
  159.     PRINT_SIZEOF(struct_e);  
  160.     PRINT_SIZEOF(struct_f);  
  161.     PRINT_SIZEOF(struct_g);  
  162.     PRINT_SIZEOF(struct_h);  
  163.     PRINT_SIZEOF(struct_i);  
  164.     PRINT_SIZEOF(struct_j);  
  165.     PRINT_SIZEOF(struct_k);  
  166.     PRINT_SIZEOF(struct_l);  
  167.     PRINT_SIZEOF(struct_m);  
  168.     PRINT_SIZEOF(struct_n);  
  169.     PRINT_SIZEOF(struct_o);  
  170.     printf("offsetof struct_n.f=%d/n", offsetof(struct_o, f));  
  171.     printf("offsetof struct_n.g=%d/n", offsetof(struct_o, g));  
  172.     PRINT_SIZEOF(CLASS_A);  
  173.     PRINT_SIZEOF(CLASS_B);  
  174.     PRINT_SIZEOF(CLASS_C);  
  175.     PRINT_SIZEOF(CLASS_D);  
  176.     PRINT_SIZEOF(CLASS_E);  
  177.     PRINT_SIZEOF(CLASS_F);  
  178.     PRINT_SIZEOF(CLASS_G);  
  179.     PRINT_SIZEOF(CLASS_H);  
  180.     PRINT_SIZEOF(CLASS_I);  
  181.   
  182.     return 0;  
  183. }  

六.例子结果

 

 

sizeof(struct_a)=12

sizeof(struct_b)=12

sizeof(struct_c)=7

sizeof(struct_d)=8

sizeof(struct_e)=12

sizeof(struct_f)=6

sizeof(struct_g)=4

sizeof(struct_h)=12

sizeof(struct_i)=2

sizeof(struct_j)=2

sizeof(struct_k)=4

sizeof(struct_l)=4

sizeof(struct_m)=28

sizeof(struct_n)=56

sizeof(struct_o)=96

offsetof struct_n.f=4

offsetof struct_n.g=40

sizeof(CLASS_A)=1

sizeof(CLASS_B)=8

sizeof(CLASS_C)=8

sizeof(CLASS_D)=16

sizeof(CLASS_E)=2

sizeof(CLASS_F)=8

sizeof(CLASS_G)=12

sizeof(CLASS_H)=8

sizeof(CLASS_I)=8

 

 

 

七.显示class的对象布局

VC8的隐含编译项/d1reportSingleClassLayout和/d1reportAllClassLayout可以看对象的布局。例如你需要看CLASS_G的对象布局,就在编译参数里面加上/d1reportSingleClassLayoutCLASS_G。更加详细的介绍请参考下面的第4个网址。下面是CLASS_G的对象布局:

class CLASS_G size(12):
+---
0 | x
| <alignment member> (size=3)
4 | CLASS_F f
+---

八.参考:

http://blog.chinaunix.net/u/20828/showart_438003.html

http://www.yuanma.org/data/2006/0723/article_1213.htm

http://blog.sina.com.cn/s/blog_59b189220100a49h.html

http://www.cnblogs.com/neoragex2002/archive/2007/11/01/VC8_Object_Layout_Secret.html

http://blog.21ic.com/user1/4861/archives/2009/61072.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中的字节对齐(内存对齐)是指在分配内存时,将变量或结构体的起始地址对齐到特定的字节边界。这样做有助于提高内存访问的效率和性能。字节对齐的规则可以通过编译器选项或特定的关键字进行控制。 以下是关于C++字节对齐的一些重要概念和规则: 1. 默认对齐: - 编译器会使用默认的对齐规则来分配内存。通常,默认对齐值是被编译器设置的,一般为结构体成员中最大的对齐值。 2. 对齐值: - 对齐值是指要求变量或结构体的起始地址必须是该值的倍数。常见的对齐值有1、2、4、8等。 3. 对齐修饰符: - C++11引入了对齐修饰符 `alignas`,允许开发者显式地指定变量或结构体的对齐值。 4. 结构体字节对齐: - 结构体的字节对齐规则是,结构体的起始地址必须是其成员中最大对齐值的倍数。 - 编译器会在结构体成员之间插入填充字节,以保证对齐要求。 5. 类对象字节对齐: - 类对象的字节对齐规则与结构体类似,但还受到继承关系的影响。 - 派生类的起始地址必须满足其成员的对齐要求,并且满足其基类中最大对齐值的倍数。 为了控制字节对齐,可以使用编译器提供的特定选项(如`#pragma pack`)或关键字(如`alignas`)。具体的字节对齐规则和选项可能因编译器平台而异,因此在编写代码时最好参考特定编译器的文档。正确的字节对齐可以提高内存访问性能,并确保与其他代码或外部系统的兼容性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值