理解-字节对齐

1、什么是字节对齐

现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

        变量存的起始地址必须具备某些特性----“对齐”,比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除。

2、为什么要进行字节对齐

  • 首先不同的硬件平台对存储空间上的处理存在不同:
  • 根本原因在于CPU访问数据的效率问题

        以32为机为例子,每次取32个位,也就是4个字节。以int型数据为例,如果在内存中存放的位置按4字节对齐,也就是说,1个int的数据全部落在了计算机一次取数的区间内,那么只需要取一次数据就可以了。如下图所示:

如果不对齐的话,如图所示:这个int跨越了读数的两个边界,这样计算机就需要两次读取才能把这个int数据全部读取到,这样效率也就降低了。

  • 节约空间

合理对齐,节约空间,否则浪费空间。

#include <stdio.h>
struct TEST1 {
    int testint;
    char testchar;
    short testshort;
} test1;

struct TEST2 {
    char testchar;
    int testint;
    short testshort;
} test2;

int main()
{
  printf("sizeof(test1):%d\n",sizeof(test1));
  printf("sizeof(test2):%d\n",sizeof(test2));
    return 0;
}

编译结果:

        结构体TEST中包含一个四字节的int数据,一个1字节char数据和2字节short数据;TEST2也一样。按理说TEST1和TEST2的大小应该都是7字节。之所以出现上述结果,就是因为编译器要对数据成员在空间上进行对齐。

3、如何对齐

3.1 基本数据类型

基本类型包括char、int、float、double、short、long等基本数据类型。

对齐要求:起始地址为其长度的整数倍即可。如,int类型的变量起始地址要求为4的整数倍。

注意:int类型的长度

理论上,int代表机器自然长度,即CPU位数,在32位CPU,应该占4字节,64位CPU,应该占8字节。
实际上,由编译器和CPU共同决定,主流的编译器编译程序将int解释为4字节。

3.2 数组

按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。

3.3 结构体

成员可以为:基本类型,复合类型(基本类型、数组、结构、联合、函数指针)
结构体中每个数据类型都要对齐,对齐值位其成员中自身对齐值最大的那个值。

3.4 联合体

联合体的内存处理取最大的成员之外还要保证是所以成员类型size的最小公倍数。

#include <stdio.h>

typedef union TEST1 {
    char testchar;
    int testint[3];
    double testshort;
} test1;

int main()
{
  printf("sizeof(test1):%d\n",sizeof(test1));
    return 0;
}

在次联合体中最大的成员位testint,其中该为长度为3的数组,最大字节为3*4=12,但是double占双精度浮点类型,占八个字节。而此时联合体已经按int的4字节对齐了,所以还要额外多加4字节的内存来保证8的倍数。所以最后结果是16。

3.5  指定对齐方式

使用伪指令#pragma pack(n):C编译器将按照n个字节对齐;
使用伪指令#pragma pack(): 取消自定义字节对齐方式。

主要是更改C编译器的缺省字节对齐方式。 

另外,还有如下的一种方式(GCC特有语法):

  • __attribute((aligned (n))): 让所作用的结构成员对齐在n字节自然边界上。如果结构体中有成员的长度大于n,则按照最大成员的长度来对齐。
  • __attribute__ ((packed)): 取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

【注】__attribute__机制是GCC的一大特色,可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。详细介绍请参考:

     Using GNU C __attribute__

让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

参考文章:

深入理解字节对齐-CSDN博客

C语言字节对齐问题详解 - clover_toeic - 博客园 (cnblogs.com)

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值