字节对齐
字节对齐原则

字节对齐原则这个问题也是困扰了我很久的⼀个问题:为了加快数据存取的速度,编译器默认情况下会对结构体成员和结构体本⾝存储位置进⾏处理,使其存放的起始地址是⼀定字节数的倍数,⽽不是顺序存放,称为字节对齐.设对齐字节数为n(n = 1,2,4,8,16),每个成员内存长度为Li,Max(Li)为最⼤的成员内存长度,字节对齐规则是:1. 结构体对象的起始地址能够被Max(Li)所整除;2. 结构体中每个成员相对于起始地址的偏移量,即对齐值应是min(n,Li)的倍数.若不满⾜对齐值的要求,编译器会在成员之间填充若⼲个字节;3. 结构体的总长度值应是min(n,Max)(Li)的倍数,若不满⾜总长度值的要求,编译器在为最后⼀个成员分配空间后,会在其后填充若⼲个字节. (VC默认的对齐字节数n=8)开不懂,请看下⾯例⼦:#include <iostream>using namespace std;// 1加1+编译器补充的2个再加上int 的4个(编译器⾃动加的)typedef struct node1 // 1+1+(2)+4 = 8{char c1;char c2;int a;}str1 ;typedef struct str2 // 1+(3)+4+1+(3) = 12{char c1;int a;char c2;}str2 ;typedef struct str3 // 5+(3)+4+2+(2) = 16{char c1[5];int b;short c;}str3 ;typedef struct str4 // 5+(1)+(2)+4 = 12{char c1[5];short c;int b;}str4 ;typedef struct str5 // 1+1+(6)+8 = 16{char c1;char c2;double a;}str5 ;typedef struct str6 // 1+(7)+8+1+(7) = 24{char c1;double a;char c2;}str6 ;typedef struct str7{char c1;str1 s; // 相当于吧str1的结构放在这 char,char,intdouble b;}str7 ; // 1+1+1+(1)+4+4 = 12int main(){str1 s1;str2 s2;str3 s3;str4 s4;str5 s5;str5 s6;str7 s7;str8 s8;cout << "s1 = " << sizeof(s1)<<endl;cout << "s2 = " << sizeof(s2)<<endl; cout << "s3 = " << sizeof(s3)<<endl; cout << "s4 = " << sizeof(s4)<<endl; cout << "s5 = " << sizeof(s5)<<endl; cout << "s6 = " << sizeof(s6)<<endl; cout << "s7 = " << sizeof(s7)<<endl; cout << "s8 = " << sizeof(s8)<<endl; return0;}图解:str1str2:str3:str4:str5:str6:。
c语言字节对齐原理

c语言字节对齐原理C语言中的字节对齐原理是指在内存中分配变量存储空间时,为了提高访问效率和内存利用率,系统会按照一定的规则进行对齐操作。
字节对齐原理在C语言中非常重要,对于程序的正确性和性能都有着重要的影响。
字节对齐的原理是为了优化内存访问速度和空间利用率,避免因为不对齐而导致的性能降低。
在C语言中,变量的存储空间是以字节为单位进行分配的,而不同的数据类型在内存中所占的字节数是不同的。
字节对齐的目的是为了确保不同类型的变量在内存中的起始地址是对齐的,这样可以提高访问效率。
C语言中的字节对齐规则是由编译器来决定的,不同的编译器可能有不同的对齐规则。
一般来说,编译器会按照变量的自然对齐大小进行对齐。
自然对齐是指变量所占的字节数,例如char类型的变量自然对齐为1字节,int类型的变量自然对齐为4字节。
在进行字节对齐时,编译器会在变量之间插入一些空白字节,使得变量的起始地址能够满足对齐要求。
这样一来,虽然会浪费一些空间,但可以提高内存的访问效率。
例如,如果int类型的变量要求按4字节对齐,而其起始地址为0x1000,那么在其后紧接着的变量的起始地址就必须是0x1004,即起始地址必须是4的倍数。
字节对齐的规则并不是固定的,它受到编译器的影响。
有些编译器的默认对齐规则可能是按照变量的自然对齐大小来对齐的,而有些编译器可能会有一些特殊的对齐规则。
此外,开发人员也可以通过编译器提供的指令来手动控制字节对齐的方式。
字节对齐的原理和规则虽然复杂,但它对于程序的正确性和性能优化至关重要。
如果变量没有按照正确的对齐方式进行存储,可能会导致内存访问错误,甚至引发程序崩溃。
而且,字节对齐也会影响程序的性能,如果变量没有按照对齐要求进行存储,可能会导致内存访问速度变慢,从而影响程序的执行效率。
为了正确地使用字节对齐,开发人员需要了解编译器的对齐规则,并且在编写代码时遵循这些规则。
在一些特殊情况下,开发人员也可以使用编译器提供的指令来手动控制字节对齐的方式,以满足特定的需求。
c语言结构体中的数组字节对齐

C语言结构体中的数组字节对齐在C语言中,结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起。
结构体中常常包含多个成员变量,其中可能有数组类型的成员变量。
在结构体中使用数组时,需要了解数组字节对齐的概念和规则,以确保内存的最佳利用和访问的效率。
什么是字节对齐字节对齐是指在将数据存储在计算机内存中时,按照特定规则进行调整,以确保数据的存储和访问的效率。
字节对齐的规则可以对齐数据的起始地址或者数据的长度。
计算机中的数据存储是按照字节(Byte)来划分的,一个字节通常由8个二进制位组成。
字节对齐的主要目的是为了节省内存和提高访问效率。
在C语言中,结构体中的成员变量通常按照字节对齐的规则来排列。
C语言结构体中的数组字节对齐规则在C语言中,结构体中的数组字节对齐规则通常遵循以下原则:1.结构体的起始地址必须是所有成员变量所要求对齐方式的最小公倍数。
2.结构体中的每个成员变量的地址必须是它本身的大小的整数倍。
3.结构体的总大小必须是其最大成员变量大小的整数倍。
根据字节对齐规则,如果结构体中的成员变量的累计大小不是字节对齐的倍数,编译器会在成员变量之间添加填充字节,以满足对齐要求。
这些填充字节在结构体的占用空间中不可访问。
填充字节的目的是将后续成员变量的地址对齐,以提高内存访问效率。
数组字节对齐的示例为了更好地理解数组字节对齐的规则,我们来看一个示例。
#include <stdio.h>struct MyStruct {char c;int i;char arr[3];};int main() {struct MyStruct s;printf("sizeof(MyStruct) = %lu\n", sizeof(struct MyStruct));printf("sizeof(s.c) = %lu\n", sizeof(s.c));printf("sizeof(s.i) = %lu\n", sizeof(s.i));printf("sizeof(s.arr) = %lu\n", sizeof(s.arr));return 0;}输出结果:sizeof(MyStruct) = 12sizeof(s.c) = 1sizeof(s.i) = 4sizeof(s.arr) = 3在这个示例中,我们定义了一个包含一个字符类型变量、一个整型变量和一个长度为3的字符数组的结构体MyStruct。
256字节对齐计算公式

256字节对齐计算公式1.引言在计算机领域,内存对齐是一种重要的概念,它与数据在内存中的存放方式密切相关。
其中,256字节对齐是一种常见的对齐方式。
本文将介绍256字节对齐的计算公式,帮助读者更好地理解和应用该对齐方式。
2.什么是内存对齐内存对齐是指变量在内存中存放时按照一定的规则对其进行排列的过程。
由于计算机硬件读取数据的机制,对齐可以提高数据的读取效率。
对齐通常以字节为单位进行,比如4字节对齐、8字节对齐等。
3.为什么选择256字节对齐在某些应用场景下,特别是在嵌入式系统或高性能计算中,选择256字节对齐可以获得更好的性能。
这是因为256字节对齐可以最大限度地利用计算机硬件的特性,提高数据的读取和处理效率。
4. 256字节对齐计算公式假设需要存放的变量为V(以字节为单位),256字节对齐的计算公式如下:A l ig ne dA dd re ss=((V+255)/256)*256其中,A li gn ed Ad dr e ss表示对齐后的起始地址。
5.举例说明为了更好地理解256字节对齐计算公式,我们来看一个具体的例子。
假设有一个结构体需要存放在内存中,其成员变量分别为:i n ta;c ha rb;d ou ble c;这三个变量的字节大小分别为4、1和8字节。
编译器为了对齐考虑,会按照最大字节大小的变量进行对齐,即8字节对齐。
首先,计算出结构体在内存中的大小:4+1+8=13字节。
然后,按照256字节对齐计算公式进行计算:A l ig ne dA dd re ss=((13+255)/256)*256=512即结构体在内存中的起始地址为512字节。
6.总结256字节对齐是一种常见的内存对齐方式,可以提高数据在内存中的读取和处理效率。
本文介绍了256字节对齐的计算公式,并通过一个具体的例子进行了说明。
希望读者通过本文的介绍,对256字节对齐有更深入的理解,并能在实际的项目中合理应用。
结构体字节对齐最简单的解释

有效对齐值与以下两种对齐值有关
1、 自身对齐值
对于单一变量,自身对齐值就是该变量所占的内存大小。
对于结构体变量,自身对齐值就是结构体成员自身对齐值中最 大的一个。
2、 指定对齐值
用程序自定对齐值。
#pragma pack(2)
//开始
#pragma pack()
//结束
代表指定 2 字节对齐
如果没有指定对齐值,那么有效对齐值就是变量的自身对齐值;如果指 定对齐值,那么有效对齐值就是这两个对齐值中的小者。
由以上说明就可以知道一个结构体变量所占的真实字节数了。
下例中所有结构体的起始地址都假设从 0 开始
例 1:
struct a
{
char no[10]; //没有指定对齐值,所有有效对齐值为自身对齐值,即
1;所以占用地址 0--9
int p;
//没有指定对齐值,所有有效对齐值为自身对齐值,即 4;
所以占用地址 12--15
long int pp; //没有指定对齐值,所有有效对齐值为自身对齐值,即
4;所以占用地址 16--19
unsigned int ppp;// 没有指定对齐值,所有有效对齐值为自身对齐
值,即 4;所以占用地址 20--23
char x; //没有指定对齐值,所有有效对齐值为自身对齐值,即 1;
所以占用地址 24
个成员结束后,所占的内存空间大小已经是有效对齐值的
整数倍了,所以不需要再加上填充字节了。
} xy;
例 2: struct S1 { char c; int i; }; struct S3 { char c1; S1 s; char c2; };
//占 8 字节 //占 16 字节
什么是字节对齐,为什么要对齐

什么是字节对齐,为什么要对齐一.什么是字节对齐,为什么要对齐?一.什么是字节对齐,为什么要对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。
一些平台对某些特定类型的数据只能从某些特定地址开始存取。
比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。
比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。
显然在读取效率上下降很多。
二.字节对齐对程序的影响:先让我们看几个例子吧(32bit,x86环境,gcc编译器):设结构体如下定义:struct A{char b;short c;};struct B{char b;int a;short c;};现在已知32位机器上各种数据类型的长度如下:char:1(有符号无符号同)short:2(有符号无符号同)int:4(有符号无符号同)long:4(有符号无符号同)float:4 double:8那么上面两个结构大小如何呢?结果是:sizeof(strcut A)值为8sizeof(struct B)的值却是12结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。
结构体字节对齐的方法

结构体字节对齐的方法全文共四篇示例,供读者参考第一篇示例:结构体字节对齐是编程中一个非常重要的概念,尤其在涉及到内存对齐的底层编程中更是不可或缺。
在结构体的定义中,每个元素都需要在内存中占用一定的空间,而结构体整体的大小受到字节对齐规则的限制。
本文将介绍结构体字节对齐的方法及其原理,希望能帮助读者更好地理解和掌握这一概念。
一、什么是字节对齐字节对齐是指在结构体中每个元素按照特定的规则分配内存空间,以便提高内存读取的效率。
在计算机系统中,一般要求数据在内存中的存储地址是某个特定值的倍数,这个特定值就是对齐系数。
常用的对齐系数有1、2、4、8等,根据不同的系统和编译器,对齐系数可能会有所不同。
二、结构体字节对齐的原理在C语言中,结构体的内存对齐是通过编译器来进行处理的。
当定义一个结构体时,编译器会按照一定的规则对结构体中的元素进行字节对齐,以便提高读取效率。
具体的对齐规则如下:1. 结构体中每个元素的偏移量必须是它自身类型大小的整数倍。
2. 结构体的大小必须是最大元素类型大小的整数倍。
3. 结构体的对齐系数为结构体中所有元素类型大小的最大值。
通过这些规则,编译器可以在编译时确定结构体的大小,并根据对齐系数进行内存对齐,从而提高内存访问的效率。
1. 使用#pragma pack指令在C语言中,可以使用#pragma pack指令来改变编译器默认的对齐系数。
通过指定pack(n)来设置n值,表示结构体的对齐系数为n。
这样可以在需要的时候自定义结构体的对齐系数,提高程序的效率。
```c#pragma pack(1)struct Student {char name[10];int age;float score;};```上面的代码中,通过#pragma pack(1)改变了结构体的对齐系数为1,从而可以确保结构体中的每个元素都按照一个字节进行对齐。
2. 使用__attribute__((packed))关键字在GCC编译器中,可以使用__attribute__((packed))关键字来实现对齐系数的设置。
C语言字节对齐__align()讲解

在设计不同 CPU 下的通信协议时,或者编写硬件驱动程序时寄存器的结构这两个地 方都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生 成的代码不一样.
一、快速理解 1. 什么是字节对齐? 在 C 语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如 int、long、 float 等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在 结构中,编译器为结构的每个成员按其自然边界(alignment)分配空间。各个成员按照它 们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。 为了使 CPU 能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对 齐”. 比如4字节的 int 型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除. 2. 字节对齐有什么作用? 字节对齐的作用不仅是便于 cpu 快速访问,同时合理的利用字节对齐可以有效地节省存储空 间。 对于32位机来说,4字节对齐能够使 cpu 访问速度提高,比如说一个 long 类型的变量,如果 跨越了4字节边界存储,那么 cpu 要读取两次,这样效率就低了。但是在32位机中使用1字节 或者2字节对齐,反而会使变量访问速度降低。所以这要考虑处理器类型,另外还得考虑编 译器的类型。在 vc 中默认是4字节对齐的,GNU gcc 也是默认4字节对齐。 3. 更改 C 编译器的缺省字节对齐方式 在缺省情况下,C 编译器为每一个变量或是数据单元按其自然对界条件分配空间。一般地, 可以通过下面的方法来改变缺省的对界条件: · 使用伪指令#pragma pack (n),C 编译器将按照 n 个字节对齐。 · 使用伪指令#pragma pack (),取消自定义字节对齐方式。 另外,还有如下的一种方式: · __attribute((aligned (n))),让所作用的结构成员对齐在 n 字节自然边界上。如果结 构中有成员的长度大于 n,则按照最大成员的长度来对齐。 · __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数 进行对齐。 4. 举例说明 例1 struct test { char x1; short x2; float x3; char x4; }; 由于编译器默认情况下会对这个 struct 作自然边界(有人说“自然对界”我觉得边界更顺 口)对齐,结构的第一个成员 x1,其偏移地址为0,占据了第1个字节。第二个成员 x2为 short 类型,其起始地址必须2字节对界,因此,编译器在 x2和 x1之间填充了一个空字节。结构的 第三个成员 x3和第四个成员 x4恰好落在其自然边界地址上,在它们前面不需要额外的填充 字节。在 test 结构中,成员 x3要求4字节对界,是该结构所有成员中要求的最大边界单元, 因而 test 结构的自然对界条件为4字节,编译器在成员 x4后面填充了3个空字节。整个结构 所占据空间为12字节。 例2 #pragma pack(1) //让编译器对这个结构作1字节对齐
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
从以上分析可以看出,采用字节对齐能提高系统性能。而编译器在编译程序时,也会 根据需要选择不同的指令来完成对数据的存取操作。
main0.s
.file "main0.c" .section ".text" .align 4 .global main .type main,#function .proc 04 main: !#PROLOGUE# 0 save %sp, -256, %sp !#PROLOGUE# 1 add %fp, -152, %o0 mov 130, %o2 mov 0, %o1 call memset, 0
现在,我们开始分析采用字节对齐和不采用字节对齐时,CPU 对于内存的访问次数有 何不同。回到图 1,先看看采用字节对齐时的情况,从图中可以看出,当 CPU 需要分别访 问 a 变量和 b 变量时,无论如何都只需要分别进行一次内存存取,图中的花括号表示一次 内存存取操作。对于不采用字节对齐的情况,a 变量无论如何只要进行一次内存操作的, 而 b 变量有可能需要进行二次内存操作,因为这一变量跨越了 4 字节的边界。这里之所以 说有可能,是因为有可能对 b 进行访问之前,可能刚好完成了对 a 的访问,而对 a 访问时, b0、b1 和 b2 也同时读入(或写入)了,这种情况下,只需要读入(或写入)b3 即可。
回到 main0.c 我们可以分析出 main 函数中的 msg 变量是 4 字节边界对齐的,因此 msg.body 是边界不对齐的,其相对于 msg 的偏移是 2 个字节(其前面有一个 2 个字节的 mark 变量)。接着程序将 msg.body 强制转换成了 header_t 结构。最终结果是 pointer 也 是边界不对齐的,这违背了 SPARC 处理器中 ld 指令要求地址边界是 4 字节对齐的限制。 这就是为什么运行这一程序会出现“Bus Error”的原因。
typedef struct {
char a; int b; } type_t;
采用字节对齐时
a
0x0000
pad
pad
pad b0
0x0004
b1
b2
b3
不采用字节对齐时
a
0x0000
b0
b1
b2 b3
0x0004
图 1 type_t 结构的内存布局示意图
在做进一步的分析之前,还需要清楚的是,对于 32 位处理器,其数据总线是 32 位的。 因此,CPU 从内存中存取数据时可以(也只能)一次读入 4 个字节。为此,CPU 从内存 中存取数据时总是以 4 字节为边界进行存取的。如果,我们所写的程序只需要访问内存中 的一个字节,此时也需要从内存中读入 4 个字节吗?是的。对于一次内存所存取的 4 个字 节中,我们是需要存取其中的 1 个字节、2 个字节或是全部 4 个字节,CPU 如何区分呢? 答案是:CPU 提供了不同的指令,而由编译器根据情况选择使用不同的指令。
其中的 stb 指令表示向内存中写入一个字节,当然,这一指令对于存取地址并无边界 对齐的要求,也就不会产生“Bus Error”这种问题了。
在默认的情况下 GCC 采用字节对齐的技术来提高程序的效率,但是有时我们不希望 这种字节对齐处理,比如两个主机进行网络通讯时,我们不需望因为字节对齐而传送多余 的字节。在这种情况下,可以在结构之前加上#pragma pack(1)编译预处理命令,它将告诉 GCC 对其后的数据结构采用一个字节对齐技术进行处理。仍然值得一提的是,不采用字节 对齐将影响程序的运行效率。下面是一段程序采用对齐技术和不采用对齐技术时汇编代码 的对比。
下面的 main1.c 程序能正常的运行。
typedef struct {
short mark; char body[128]; } msg_t;
main1.c
int main () {
msg_t msg = {0}; msg.body[1] = 3; return 0; }
这是因为编译器知道 body[1]是一个字节,因此不会采用类似 ld 这样存取 4 字节的指 令,这可以从 main1.c 的汇编代码看出,如下所示。
为什么这么简单的一个程序在不同的操作系统(其实是处理器)上的运行结果却决然 不同?这其实是一个 CPU 字节对齐所引发的问题,下面我们通过对字节对齐问题的分析来 探究其背后的原理。后面的分析我们全部是针对运行在 32 位 SPARC 处理器上的 Solaris 操作系统进行的。
2 为什么要字节对齐
简单的说来就是为了提高 CPU 的性能,或者说是提高程序运行的效率。当然,在其背 后更有简化 CPU 设计的功效。因此,我们所写的 C 程序为了得到尽可能高的效率就必须 最大限度的满足 CPU 对于字节对齐的要求,编译器在这当中起着至关重要的作用。
main0.c
typedef struct {
short mark; char body[128]; } msg_t;
typedef struct {
char *pointer; } header_t;
int main ()
█1
C 语言中一个字节对齐问题的分析 { msg_t msg = {0}; void *p = ((header_t *)msg.body)->pointer; return 0; }
关键词
C 语言
参考资料
字节对齐
[1] The SPARC Architecture Manual v8
1 问题的引入
下面是一段被简化的程序,分别在 Windows(32 位的 x86 处理器)和 Solaris(32 位 的 SPARC 处理器)上编译和运行,其结果将完全不同。在 Windows 上程序运行正常,但 是在 Solaris 上程序运行会出错,并且会在终端上打印出“Bus Error”以及产生一个“Core dump”文件。
其中的 halfword 是指 2 个字节,word 是指 4 个字节,而 doubleword 是指 8 个字节。 这段话给我们的信息是:当使用 ld 指令从内存中读入一个 4 字节的字时,其地址必须是以 4 字节为边界对齐的。
前面说到 C 语言对于数据结构的对齐还有一个很重要的问题是:C 语言除了对结构进 行对齐外(从结构内部的角度),还需要将进行字节对齐处理过的结构变量(从结构的外部 角度)分配在以 4 字节为边界的地方才有意义,比如图 1 中的 type_t 变量如果不是放在 0x0000 地址(4 字节边界对齐)上,而是放在 0x0001 的地址上,则边界对齐的结构也会 变成边界不对齐。因此,我们可以推理,所有的全局变量或是局部变量,在内存中都应当 分配在 4 字节边界对齐的地方(这样的话编译器的设计最为简单),只有这样 C 语言(编 译器)对于边界对齐的处理才算是完整的。
nop ld [%fp-150], %o0 st %o0, [%fp-156] mov 0, %o0 mov %o0, %i0 nop ret restore .LLfe1: .size main,.LLfe1-main .ident "GCC: (GNU) 3.2.3"
其中需要注意的是 SPARC 处理器中的 ld 指令,这一指令从内存中读入一个 4 字节的
typedef struct {
char *pointer; } header_t;
{0}; void *p = ((header_t *)msg.body)->pointer; return 0; }
由于 header_t 结构中只有一个指针变量 pointer,指针是 32 位的,易于字节对齐。因 此,编译器对于所有 pointer 的访问都采用 32 位的存取指令。这可以通过查看 main0.c 的 汇编代码 main0.s 来验证,如下所示。
typedef struct {
char a; short b; } element_t;
下面我们来分析为什么进行字节对齐能提高运行效率。要对数据结构进行更为高效的
2█
C 语言中一个字节对齐问题的分析
操作,从 CPU 的角度来看就是尽可能减少 CPU 对内存的访问次数。对于 type_t 结构,其 内存布局如图 1 所示,需要指出的是 SPARC 是 big-endian 模式,图中的 b=b0b1b2b3。
对于 C 程序员,大部分情况下我们并不考虑字节对齐问题,这并不是说我们不需要考虑,而是 因为碰到这种问题的情况很少。一方面要在特定的处理器上,而另一方面和我们写的程序也有关系, 只有两个条件同时满足时问题才会出现。因此,结果给我们的感觉是“字节对齐与我无关”。
本文通过对一小段简单的代码在不同处理器上的运行结果引出对字节对齐问题的关注,同时对 其原因进行了分析。
下面的 C 程序编译后运行,在终端上将会打印出“size of type_t is 8”。为什么是 8 而 不是 5 呢?这是因为编译器考虑到了运行效率从而将 type_t 结构进行了 4 字节边界对齐的 处理。
#include <stdio.h>
typedef struct {
char a; int b; } type_t;
int main () {
printf ("size of type_t is %d\n", sizeof (type_t)); return 0; }
这里需要指出的是,编译器会根据具体的结构选择是 4 字节边界对齐还是 2 字节边界 对齐。比如,下面定义的 element_t 结构,其 sizeof 大小应当是 4,而不是 3,更不会是 8。