原始链接源自 https://www.cnblogs.com/clover-toeic/p/3853132.html , 从上面博客中学习总结得到下面的文章。

不同硬件平台,对存储空间的处理不一样,比如不能放奇数地址,不能任意存放等,为了适应不同的架构,在C语言层面上,就可以执行对齐从而独立于硬件平台。 此外,是由于对内存的存取效率问题,如果存放的地址不对齐,取一个4字节的数据,可能会需要两个时钟信号才能取完。为了CPU能够对数据进行快速的访问,也要求数据的起始地址具有对齐特性。 比如4字节数据的起始地址应该在4字节的边界上,也就是数据存放的起始地址应该被4整除。这就是为什么要字节对齐, 和什么是字节对齐。

对齐的方式,又区分 结构体对齐、 栈内存对齐、位域对齐, 位域本质上是结构体。

对于Intel X86平台,每次分配内存应该是从4的整数倍地址开始分配,无论是对结构体变量还是简单类型的变量。

一、结构体对齐
    编译器为结构体的每个成员按照其自然边界(alignment)分配空间。各成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

对齐规则:

1) 数据类型自身的对齐值:char型数据自身对齐值为1字节,short型数据为2字节,int/float型为4字节,double型为8字节。

2) 结构体的自身对齐值:其成员中自身对齐值最大的那个值

3) 指定对齐值:#pragma pack (value)时的指定对齐值value。默认是4。

4) 数据成员、结构体的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}。

使用pragma指定对齐值,其实是指定了数据结构的最大对齐值, 如果本身的对齐值,并不超过设定的值,还是会按照自身的对齐值来。

有效对齐值N是最终用来决定数据存放地址方式的值。有效对齐N表示“对齐在N上”,即该数据的“存放起始地址%N=0”。结构体的成员变量要对齐存放,结构体本身也要根据自身的有效对齐值圆整(即结构体成员变量占用总长度为结构体有效对齐值的整数倍)。

struct A{int    a;char   b;short  c;
};
struct B{char   b;int    a;short  c;
};

sizeof(A) = 8,  sizeof(B) = 12;

A中,最初的int是4字节对齐,char是1字节对齐,所以前5个字节不需要填充,后面short长度为2个字节,和2对齐,所以char后面补一个字节,总共是8个字节。整个数组的有效对齐值是成员的最大值4, 8个字节是4的整数倍, 所以结构体总长度为8。

B中,最初char是1字节,随后int长度是4字节,和4字节对齐,char后面补3个字节,最后short是第9和10字节,也是对齐的。整个结构体的有效对齐值是4,结构体长度需要是4的整数倍,所以short后面还需要补2个字节,总长度为12。

之所以编译器在后面补充2个字节,是为了实现结构数组的存取效率。试想如果定义一个结构B的数组,那么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都紧挨着。如果我们不把结构体大小补充为4的整数倍,那么下一个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐。因此要把结构体补充成有效对齐大小的整数倍。

更改对齐方式:

在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对界条件:
    使用伪指令#pragma pack(n):C编译器将按照n个字节对齐;
    使用伪指令#pragma pack(): 取消自定义字节对齐方式。

在编码时,可用#pragma pack动态修改对齐值。自定义对齐值后要用#pragma pack()来还原,否则会对后面的结构造成影响。

#pragma pack(2)  //指定按2字节对齐
struct C{char  b;int   a;short c;
};
#pragma pack()   //取消指定对齐,恢复缺省对齐

char自身对齐值是1,指定对齐值是2,所以有效对齐值是1。 int自身对齐值是4,指定对齐值是2,所有有效对齐值是2,放在2的倍数的地址空间上,char后面只会补1个字节。所以到这里长度是6,后面short两个字节,有效对齐值也是2,结构体总长度是8。

需要注意,pragma pack指定的对齐值,是数据类型的最大对齐值,可以小,但是不能大。

因为对齐,会产生的问题:

1,数据类型强转可能会因为对齐,出错。 short类型应该放在2的倍数的地址上,但是这里p1却指向了奇数地址。需要注意。

int main(void){  unsigned int i = 0x12345678;unsigned char *p = (unsigned char *)&i;*p = 0x00;unsigned short *p1 = (unsigned short *)(p+1);*p1 = 0x0000;return 0;
}

2,不同的处理器之间传递数据时,因为两个处理器可能采用的填充方式不一致,会导致数据出错。这时,可以在定义数据结构时,自己把需要填充的部分用char类型的数据填上,这样就不会不一致了。或者使用pragma pack 1, 让数据都按照1字节对齐。

二、栈内存对齐

在VC/C++中,栈的对齐方式不受结构体成员对齐选项的影响。总是保持对齐且对齐在4字节边界上。(直接看博客原文吧,他里面说的char和short没有凑到4个字节,我认为是已经凑到一起了)。

三、位域的对齐方式

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间和处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。

1,为了节省内存,对于大量的结构体数组来讲。 2,需要访问字节内的bit成员。两种情况会使用位域。

位域成员,除了指定所占用的bit位外,还有一个类型。位域成员不能单独被取sizeof值。下面主要讨论含有位域的结构体的sizeof。

其对齐规则大致为:

1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++和GCC采取压缩方式;

4) 如果位域字段之间穿插着非位域字段,则不进行压缩;

5) 整个结构体的总大小为最宽基本类型成员大小的整数倍,而位域则按照其最宽类型字节数对齐。

位域可以无位域名,只用作填充或调整位置,占位大小取决于该类型。例如,char :0表示整个位域向后推一个字节,即该无名位域后的下一个位域从下一个字节开始存放,同理short :0和int :0分别表示整个位域向后推两个和四个字节。

当空位域的长度为具体数值N时(如int :2),该变量仅用来占位N位。

原文还有位域的例子和字节大小端的例子,在这里就不写了。

C语言字节对齐规则总结相关推荐

  1. C语言结构体字节对齐规则

    C语言结构体字节对齐规则 基本规则 规则1 :结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的地方(比如int在 ...

  2. 程序人生 | C语言字节对齐问题详解 - 对齐/字节序/位序/网络序等(上)

    本文首发于 2014-07-21 15:32:28 1. 引言 考虑下面的结构体定义: typedef struct{char c1;short s; char c2; int i; }T_FOO; ...

  3. C语言字节对齐问题详解

    转载原文连接:https://www.cnblogs.com/clover-toeic/p/3853132.html C语言字节对齐问题详解 引言 考虑下面的结构体定义: 1 typedef stru ...

  4. 结构体对齐(字节对齐)规则及大小计算

    什么是字节对齐 这跟读取数据有关,cpu读取一次能读取到的内存大小跟数据总线的位数有关,如果数据总线为16位,那么cpu一次能够读取2字节:如果为32位那么cpu一次可以读取4字节,而读取数据是需要消 ...

  5. c语言强制4字节对齐,C语言字节对齐4

    非字节对齐类型的字节对齐规则 我们可以使用"__packed"."__attribute__((packed))"."#pragma"等方式 ...

  6. (转)C语言字节对齐

    图片可以在下面的博客中看到. 转自:http://blog.csdn.net/bigloomy/article/details/6633008 可能有不少读者会问,字节对齐有必要拿出来单独写一篇博客嘛 ...

  7. c如何通过偏移量取出文件中的字节_理一理C语言字节对齐的那些事

    作者:守望,Linux应用开发者,目前在公众号[编程珠玑] 分享Linux/C/C++/数据结构与算法/工具等原创技术文章和学习资源. 前言 字节对齐是我们初学C语言就会接触到的一个概念,但是到底什么 ...

  8. c语言4字节对齐,理一理C语言字节对齐的那些事

    前言 字节对齐是我们初学 C语言 就会接触到的一个概念,但是到底什么是字节对齐?对齐准则又是什么?为什么要字节对齐呢?字节对齐对我们编程有什么启示?本文将简单理一理字节对齐的那些事. 什么是字节对齐 ...

  9. C语言字节对齐问题详解(zz)

    http://www.bubuko.com/infodetail-263205.html 引言 考虑下面的结构体定义: typedef struct{char c1;short s; char c2; ...

最新文章

  1. @async 默认线程池_.NET Web应用中为什么要使用async/await异步编程?
  2. ISE include 头文件错误的解决办法
  3. 自用零散博文-route_state.ts
  4. 15.枚举enum.rs
  5. zigbee板子:lcd显示汉字
  6. 为什么 MapReduce 再次流行起来了?
  7. *与**在python中的使用
  8. css3媒体查询尺寸
  9. 小程序:微信小程序开发
  10. Linux_I2C读写流程
  11. CCNA题库第一部分
  12. c语言:输出一个菱形图案
  13. Python爬虫——糗百
  14. 金山wps支持java接口开发吗_金山wps开放平台使用踩坑实录
  15. MBR10100FCT-ASEMI肖特基二极管MBR10100FCT
  16. Ninth season twenty-first episode,Chandler and Monica may never have children??????
  17. SQL开窗函数(窗口函数)详解
  18. Qt帮助文档无法打开的解决方案
  19. Ping不通的原因分析
  20. 利用菜单配置文件生成菜单

热门文章

  1. 你们想要知道的跳一跳都在这了,23333333
  2. 福特汉姆大学计算机科学专业,留学福特汉姆大学专业
  3. 微信小程序在线知识答题有奖多开版源码
  4. style.left不起作用的问题
  5. dns 劫持是什么意思,DNS劫持有啥解决办法?
  6. 1919获阿里20亿投资,独角兽如何搅动酒饮业格局
  7. openStack 常见问题及解决
  8. 四轴基本知识扫盲及资料收集
  9. MySQL8.0超细致下载安装教程
  10. linux脚本:每天晚上 12 点,打包站点目录/var/www/html 备份到/data 目录下