结构体字节对齐问题
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。
4字节对齐原理

4字节对齐原理小伙伴,今天咱们来唠唠4字节对齐这个超有趣的计算机原理。
你知道吗?这就像是计算机世界里的一种小默契呢。
在计算机的存储世界里啊,数据就像住在一个个小房子里,这些小房子就是字节。
4字节对齐就像是一种特殊的居住规则。
想象一下,字节们组成了一条条街道,每个数据都有自己的住所。
4字节对齐就是说,数据最好住在那些地址是4的倍数的小房子里。
为啥要有这样的规则呀?这可就大有讲究啦。
从计算机硬件的角度看,很多硬件设备在读取数据的时候,一次读取4个字节会特别高效。
就好像你去超市买东西,如果东西都按照一定的组合包装好,你拿起来就很方便。
计算机的处理器也是这样,如果数据按照4字节对齐,处理器一下子就能把它需要的数据整整齐齐地拿过来,就像你轻松拿起一组包装好的商品一样,速度那叫一个快。
而且哦,这种对齐方式还和数据的安全性、稳定性有关系呢。
如果数据是乱七八槽地存放,就像一群调皮的小动物没有住在自己该住的地方,很容易就会出乱子。
比如说,可能会出现数据被错误解读的情况。
但是按照4字节对齐,数据就像规规矩矩排好队的小朋友,大家都清楚自己的位置,不会搞混。
咱们再从软件的角度看看。
编写程序的程序员们也很喜欢4字节对齐呢。
因为这可以让程序运行得更流畅。
当程序需要调用数据的时候,如果数据是4字节对齐的,就像是走在一条规划好的平坦大道上,没有坑坑洼洼。
要是不按照这个规则,程序可能就会像一个在崎岖小路上行走的人,磕磕绊绊的。
比如说,有一个结构体,里面有不同类型的数据。
如果按照4字节对齐来安排这些数据的存储位置,那么这个结构体在内存中的布局就会特别整齐。
这就好比你整理自己的书架,按照一定的规则把书分类摆放,找起书来就特别容易。
在一些大型的软件项目里,4字节对齐更是起到了关键的作用。
就像一个大型的合唱团,每个成员都要站在自己该站的位置上,这样整个合唱团才能唱出和谐美妙的歌曲。
如果数据不按照4字节对齐,就像合唱团里有人站错了位置,那唱出来的歌可就不好听啦,程序也会出现各种莫名其妙的问题。
小议结构体变量的字节对齐

信 息科 学
小议 结构体变量 的字节对齐
杨 善 红
( 川理 工 学 院计 算 机 学 院 , 川 自贡 6 3 0 ) 四 四 4 0 0
摘 要: 为了提高 C U访 问内存效率, P 编译器一般会对结构体 变量进行字节对 齐。文章结合 示例深入研讨 了src,no ,i Fe t tu in Bt id字节对齐和 u l 内存分配规则 , 为实际编程实现 中提供参考。 关键 词 : c a l n N trlA i ;pama s ef pd ig A t lAi ; a a l n # rg i o adn u g u g z 以 3 位 It P 2 ne C U为例(6和 6 l 1 4位类同)一次可以对一个 3 位的数 员实 际 Ain值 。 , 2 l g 2ary数组实际 Mi 值等于该数组成员的实际 A i 值。 )r a n g ln g 进行运算, 它的数据总线的宽度是 3 2位, C U字长为 3 即 P 2位。 1 为什么要进行字节对齐 3ui 联合实际 Ai 值等于 冶 最大皖员 ) o nn ln g 实际 Ai 值。 l n g 4在 AN I ) S C中规定位域的类型只能为 s nd nindit, i e/ s e 但各厂家 g u g n 先看下图, 假设 ln 1 l g 变量内存分配结构如下 : og 和 o 2 n 1 8 1 2 3 6 4 2 ln ll g 类型都为 ln , n l og ,n 2 o o gl g 在 都对其进行了扩展, o 类型可以是 c a hr l g h so ,o 等但其最大长度不能超过 t n 内存 中的 位 置 正 好 与 内 存 字边 界 对 齐 , i 的长度, 3 位平台时为 3 位, 位平台时为 1 位。 n t 即 2 2 1 6 6 位域存储空间的分 P 配也与各编译器的实现有关, 而且与小字节序 ( 69o ' x '6 i 8i l 大字节序 (8 x, 6 00
C语言结构体对齐问题

C语言结构体对齐问题1。
几个结构体例子:struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B;sizeof( A)=6, sizeof( B)=8,为什么?注:sizeof(short)=2,sizeof(long)=4因为:“成员对齐有一个重要的条件,即每个成员按自己的方式对齐。
其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐。
并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。
”(引用)结构体A中有3个short类型变量,各自以2字节对齐,结构体对齐参数按默认的8字节对齐,则a1,a2,a3都取2字节对齐,则sizeof(A)为6,其也是2的整数倍;B中a1为4字节对齐,a2为2字节对齐,结构体默认对齐参数为8,则a1取4字节对齐,a2取2字节对齐,结构体大小6字节,6不为4的整数倍,补空字节,增到8时,符合所有条件,则sizeof(B)为8;可以设置成对齐的#pragma pack(1)#pragma pack(push)#pragma pack(1)struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B;#pragma pack(pop)结果为sizeof( A)=6,sizeof( B)=6 ************************#pragma pack(8)struct S1{char a;long b;};struct S2 {char c;struct S1 d;long long e;};#pragma pack()sizeof(S2)结果为24.成员对齐有一个重要的条件,即每个成员分别对齐,即每个成员按自己的方式对齐。
也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐。
ARM中的对齐问题

ARM中的对齐问题
在ARM 中,当吧一个内存区域初始化为某个结构体时,必须注意字节对
齐情况。
1. 简介
在ARM 中,有ARM 和Thumb 两种指令。
ARM 指令:每执行一条指令,PC 的值加4 个字节(32bits).一次访问4 字节内容,该字节的起始地址必须是4 字节对齐的位置上,
即地址的低两位为bits[0b00],也就是说地址必须是4 的倍数。
Thumb 指令:每执行一条指令,PC 的值加2 个字节(16bits).).一次访问2 字节内容,该字节的起始地址必须是2 字节对齐的位置上,
即地址的低两位为bits=0,也就是说地址必须是2 的倍数。
遵循以上方式叫对齐(aligned)方式,不遵守这样方式称为非对齐(unaligned)的存储访问操作。
ARM CPU 不支持未对齐双字(8 bytes)访问。
双字访问必须是8 字节/4 字节对齐.
2. ARM 平台中的字节对齐关键字
(1) __align(num)
(2) __packed
进行一字节对齐。
(3) __unaligned
用于修饰某个变量,可按照非对齐方式访问。
3. __packed 与#pragma pack(1)的区别
4. __attribute__((aligned))
用于指定类型的最低对齐要求.。
iar默认字节对齐方式

iar默认字节对齐方式
字节对齐是计算机领域中一个重要的概念,它决定了数据在内存中的存储方式。
在计算机中,数据以字节为单位进行存储和传输。
字节对齐指的是数据在内存中的存储位置必须是某个特定值的倍数。
这个特定值被称为对齐单位。
字节对齐的原因是为了提高计算机的运行效率。
当数据按照对齐单位进行存储时,CPU读取数据的速度更快。
如果数据的存储位置不满足对齐要求,CPU需要经过额外的计算来获取数据,这会影响计算机的性能。
在C语言中,默认的字节对齐方式是按照结构体中最宽基本类型的大小进行对齐。
例如,如果结构体中包含有int和char两种类型的成员变量,那么结构体的对齐单位就是int的大小。
这意味着结构体中的每个成员变量的地址必须是int大小的倍数。
字节对齐还可以通过编译器的预处理指令来进行控制。
在C语言中,可以使用#pragma pack指令来指定对齐方式。
例如,可以使用#pragma pack(1)来告诉编译器按照1字节对齐。
字节对齐可以避免内存对齐问题带来的性能损失。
当数据按照对齐要求存储时,CPU可以更高效地读取和写入数据,提高计算机的运行速度。
所以,在编写程序时,应该充分考虑字节对齐的问题,合理安排数据的存储方式,以提高程序的性能。
字节对齐是计算机中一个重要的概念,它决定了数据在内存中的存储方式。
通过合理安排数据的存储位置,可以提高计算机的运行效率。
在编写程序时,应该充分考虑字节对齐的问题,以提高程序的性能。
结构体字节对齐的方法

结构体字节对齐的方法全文共四篇示例,供读者参考第一篇示例:结构体字节对齐是编程中一个非常重要的概念,尤其在涉及到内存对齐的底层编程中更是不可或缺。
在结构体的定义中,每个元素都需要在内存中占用一定的空间,而结构体整体的大小受到字节对齐规则的限制。
本文将介绍结构体字节对齐的方法及其原理,希望能帮助读者更好地理解和掌握这一概念。
一、什么是字节对齐字节对齐是指在结构体中每个元素按照特定的规则分配内存空间,以便提高内存读取的效率。
在计算机系统中,一般要求数据在内存中的存储地址是某个特定值的倍数,这个特定值就是对齐系数。
常用的对齐系数有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))关键字来实现对齐系数的设置。
c51结构体对齐方式

c51结构体对齐方式
C51是一种常见的8位单片机,它使用的是Keil C51编译器。
在C51中,结构体的对齐方式是由编译器的设置和结构体成员的类型来决定的。
结构体对齐方式影响了结构体成员在内存中的存储方式,它可以通过编译器的设置来进行调整。
在C51中,默认的结构体对齐方式通常是按照成员的大小进行对齐,也就是说,结构体成员会被放置在能够容纳其大小的内存地址上。
这样做的好处是可以提高内存的访问效率,但是可能会导致内存空间的浪费。
另外,在C51中,也可以通过编译器的设置来指定结构体的对齐方式。
通过设置#pragma pack指令,可以改变默认的对齐方式,使得结构体成员按照指定的对齐方式进行排列。
例如,可以使用
#pragma pack(1)来指定按照1字节对齐,这样可以减少内存空间的浪费,但可能会影响内存的访问效率。
总的来说,C51中结构体的对齐方式可以通过编译器的设置来进行调整,可以根据实际的需求来选择合适的对齐方式,以达到内
存利用和访问效率的平衡。
结构体对齐方式的选择需要根据具体的应用场景和硬件平台来进行权衡和调整。
结构体字节对齐packed

结构体字节对齐typedef __packed struct之前一直很少用结构体,但最近随着变量的直线上升,不得不采用结构体。
对于struct,理解并不是很深入,最近一段时间的应用,发现struct的强大。
作为一种数据集合,struct常用在数据结构中。
而struct的字节对齐方式对于嵌入式底层的程序员来讲是必须掌握的。
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。
一些平台对某些特定类型的数据只能从某些特定地址开始存取。
比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。
比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。
显然在读取效率上下降很多。
下面看一个例子(32bit,x86环境,VC++6.0编译器):struct A{int a;char b;short c;};struct B{char b;int a;short c;};我们知道在VC++6.0中,以上几种数据类型的长度如下:char: 1;int: 4;short:2;以上两个结构体的大小如下:sizeof(strcut A)值为8sizeof(struct B)值是12;结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B 也一样;按理说A,B大小应该都是7字节。
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字节对齐
c语言4字节对齐指令

C语言4字节对齐指令一、什么是对齐指令1.1 对齐的概念在计算机中,对齐是指数据在内存中存储的方式。
内存中的数据是以字节为单位进行存储的,而对齐就是数据在内存中存储时的起始位置需要与其自身的大小对齐。
1.2 对齐的优势对齐的目的是为了提高计算机的访问速度。
当数据对齐之后,CPU的访问操作会更加高效,从而提高程序的执行效率。
二、数据对齐的原则数据的对齐有一定的规则,其中最常见的是按照字节对齐的原则进行排列。
2.1 字节对齐原则在C语言中,数据的字节对齐原则是根据数据类型的大小来确定的。
一般来说,对于基本数据类型,其对齐规则如下所示:•char类型不需要对齐,可以从任意位置开始存储。
•short类型需要2字节对齐,即起始地址必须是2的倍数。
•int类型需要4字节对齐,即起始地址必须是4的倍数。
•long类型需要8字节对齐,即起始地址必须是8的倍数。
2.2 结构体对齐原则对于结构体中的成员变量,其对齐规则也是按照字节对齐的原则进行排列的。
结构体中的成员变量按照其自身的大小顺序存放,并且每个成员变量的起始地址需要满足对齐规则。
三、C语言的对齐指令C语言提供了一些对齐指令,可以用来控制数据的对齐方式。
对齐指令可以通过编译器的选项来设置,也可以使用特殊的关键字进行设置。
3.1 编译器选项设置对齐方式编译器提供了一些选项来设置数据的对齐方式,其中最常用的是-malign-double 选项。
该选项可以控制double类型的对齐方式,一般情况下,我们可以将其设置为-malign-double=8,表示使用8字节对齐方式。
3.2 结构体的对齐指令在C语言中,可以使用#pragma pack(n)指令来设置结构体的对齐方式。
其中n表示对齐的字节数,常用的值为1、2、4、8等。
3.3 成员变量的对齐指令对于结构体中的某个成员变量,可以使用__attribute__((aligned(n)))指令来单独设置其对齐方式,其中n表示对齐的字节数。
c语言结构体对齐原因

c语言结构体对齐原因C语言结构体对齐是为了提高内存访问的效率。
在计算机系统中,访问内存是一种相对较慢的操作,为了最大化地利用内存和提高访问效率,计算机系统一般会按照一定的规则将变量和数据结构存储在内存中。
结构体对齐就是其中一种规则。
结构体对齐的目的是为了按照一定的规则在结构体中插入一些无意义的填充字节,使结构体的起始地址和所有成员变量的地址都满足对齐要求。
这样就可以保证在读取、写入结构体中的成员变量时,不需要额外的计算和操作,提高了内存的访问效率。
结构体对齐主要有以下几个原因:1.CPU的读取效率:CPU在读取内存中的数据时,一次读取的数据量是有限的,一般情况下是一个字(4字节或8字节)。
如果结构体中的成员变量不满足对齐要求,就需要进行额外的读取操作,这样就会降低CPU读取数据的效率。
而对齐后的结构体中的成员变量地址是连续的,可以通过一次读取操作将整个结构体读入CPU,提高了读取效率。
2.总线带宽的利用率:在CPU和内存之间有一组数据传输线,称为总线。
总线的传输速度是有限的,一般是以字节为单位的。
如果结构体中的成员变量不满足对齐要求,就需要额外的传输操作,这样就会浪费总线的带宽资源。
而对齐后的结构体中的成员变量地址是连续的,可以通过一次传输操作将整个结构体传输到总线上,提高了总线带宽的利用率。
3.缓存的利用效果:在CPU和内存之间有一级或多级缓存,用来暂存需要频繁读取的数据。
缓存的读取速度比内存快很多,但是缓存的容量是有限的。
如果结构体中的成员变量不满足对齐要求,就会导致结构体的大小增加,从而无法完全缓存在高速缓存中,降低了缓存的利用效果。
而对齐后的结构体中的成员变量地址是连续的,能够更好地利用缓存的容量,提高了缓存的利用效果。
4.硬件的要求:一些硬件设备对数据的对齐要求非常严格,如果数据不满足对齐要求,读取或写入操作可能会导致硬件错误。
为了保证程序的正确性和稳定性,结构体对齐是必要的。
结构体对齐是由编译器自动完成的,编译器会根据编译器设置的对齐规则来进行对齐。
字节对齐(强制对齐以及自然对齐)

字节对齐(强制对齐以及⾃然对齐)struct {}node;32为的x86,window下VC下sizeof(node)的值为1,⽽linux的gcc下值为0;⼀、WINDOWS下(VC--其实GCC和其原理基本⼀样,象这种问题,⼀般要查具体的编译器设置)字节对齐的规则:1、⼀般设置的对齐⽅式为1,2,4字节对齐⽅式,VC⼀般默认为4字节(最⼤为8字节)。
结构的⾸地址必须是结构内最宽类型的整数倍地址;另外,结构体的每⼀个成员起始地址必须是⾃⾝类型⼤⼩的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最⾼为4字节对齐),否则在前⼀类型后补0;这⾥特别提到的是数组⼀定要注意,⽽且在⼀些编程的技巧中,我们可以使⽤数组强制字节达到对齐的⽬的。
这在⽹络编程中是很常见的。
举例:⽐如CHAR型占⽤空间为1字节,则其起始位置必须可被1整除。
INT为4字节,其起始位置必须被4带队,依次类推。
(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。
)2、结构体的整体⼤⼩必须可被对齐值整除,默认4(默认,且结构中的类型⼤⼩都⼩于默认的4)。
3、结构体的整体⼤⼩必须可被本结构内的最宽类型整除。
(其实和上⼀条是⼀样的,但这⾥独⽴出来,起注意作⽤。
⽐如结构体⾥的有DOUBLE,那么结构的⼤⼩最后必须可被8整除)注意:GCC不是这样,就是最⾼只能被4整除,它是个死的。
否则(2、3条),编译器会在结构的最后添充⼀定的特定字符来补齐。
struct T{char ch;double d ;};在VC中是16个字节,GCC中为12个字节。
4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,⽽不能以嵌套结构⼤⼩来做为上三种使⽤的基准。
⼆、举例:struct A{int a;char b;short c;};struct B{char b;int a;short c;};struct C{double t;char b;int a;short c;};struct D{char b;double t;int a;short c;};在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;我们先谈第⼀个,(说明⼀下,在考虑结构体⼤⼩时,我们基本可以忽略起始地址的问题,因为这个编译器会⾃动为我们做好,见上⾯的说明),结构体内⾸先是⼀个INT的4字节,起始地址假定为0,整除4,其⼩于等于默认的4字节对齐且0为4(INT的占⽤空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,⼩于4且5为1(CHAR占⽤空间)的整数倍,故占⽤1个字节,然后是⼀个起始地址为5占2个字节的SHORT,其⼩于4,但5不为2的整数倍,故补齐⼀个字节,从第6个字节开始,占2字节空间。
结构体对齐方式

结构体对齐方式
结构体对齐方式是指在内存中如何对结构体的成员进行排列和对齐。
通常,结构体的对齐规则是将结构体的成员按照从高到低的顺序排列,并且要求成员的起始地址是其大小的整数倍。
即结构体的对齐要求成员的起始地址必须满足某种对齐大小。
一般来说,结构体的对齐方式会依赖于编译器的实现和目标平台的要求。
但是,可以使用一些特定的指令或编译选项来控制结构体的对齐方式。
常用的结构体对齐方式有以下几种:
1. 默认对齐方式:结构体成员的对齐方式由编译器和目标平台决定,通常是按照成员的类型进行对齐。
2. 最大对齐方式:结构体的对齐方式取决于其成员中最大的对齐要求。
即结构体的对齐大小是成员中最大对齐要求的整数倍。
3. 最小对齐方式:结构体的对齐方式取决于其成员中最小的对齐要求。
即结构体的对齐大小是成员中最小对齐要求的整数倍。
结构体的对齐方式可以通过编译器的指令或选项进行控制,例如使用#pragma pack(n)指令来指定结构体的对齐方式为n字节。
或者在编译时使用特定的选项,例如-gcc的-fpack-struct选项
来指定结构体的对齐方式为默认方式。
内存对齐(结构体和Union)

}AA;
int main()
{
AA a;
cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;
return 0;
}
结果是
48 24
ok,上面的全看明白了,内存对齐基本过关.
明白了不?
那#pragma pack(2)的结果又是多少呢?对不起,5分钟到了,自己去测试吧.
===============================================================
一会搞定union内存字节对齐
也是转载一个论坛的回复:
其实union(共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点:
等你看完此3条原则,2分钟已经过去,抓紧时间,实战3分钟:
typedef struct bb
{
int id; //[0]....[3]
double weight; //[8].....[15] 原则1
float height; //[16]..[19],总长要为8的整数倍,补齐[20]...[23] 原则3
char a;//元长度1
int b[5];//元长度4
double c;//元长度8
int d[3];
};
本来mm的空间应该是sizeof(int)*5=20;但是如果只是20个单元的话,那可以存几个double型(8位)呢?两个半?当然不可以,所以mm的空间延伸为既要大于20,又要满足其他成员所需空间的整数倍,即24
c++中的字节对齐规则

struct A
{
int a;
char b;
short c;
};
struct B
{
char b;
int a;
short c;
};
现在已知32位机器上各种数据类型的长度如下:
char:1(有符号无符号同)
6.对齐或非对齐读写访问带来问题
__packed struct STRUCT_TEST
{
char a;
int b;
char c;
} ; //定义如下结构此时b的起始地址一定是不对齐的
//在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]
一.什么是字节对齐,为什么要对齐?
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访
问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一
个的排放,这就是对齐。
#pragma pack (2) /*指定按2字节对齐*/
struct C
{
char b;agma pack () /*取消指定对齐,恢复缺省对齐*/
第 一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合
们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入reserved成员:
struct A{
char a;
char reserved[3];//使用空间换时间
结构体字节对齐问题

结构体字节对齐问题原帖:为了避免混淆,做如下规定,以下代码若不加特殊说明都运⾏于32位平台,结构体的默认对齐值是8,各数据类型所占字节数分别为char占⼀个字节int占四个字节double占⼋个字节。
两个例⼦请问下⾯的结构体⼤⼩是多少?struct Test{char c ;int i ;};这个呢?struct Test1{int i ;double d ;char c ;};在公布答案之前先看⼀下对齐的规则。
对齐规则⼀般来说,结构体的对齐规则是先按数据类型⾃⾝进⾏对齐,然后再按整个结构体进⾏对齐,对齐值必须是2的幂,⽐如1,2, 4, 8,16。
如果⼀个类型按n字节对齐,那么该类型的变量起始地址必须是n的倍数。
⽐如int按四字节对齐,那么int类型的变量起始地址⼀定是4的倍数,⽐如 0x0012ff60,0x0012ff48等。
数据⾃⾝的对齐数据⾃⾝的对齐值通常就是数据类型所占的空间⼤⼩,⽐如int类型占四个字节,那么它的对齐值就是4整个结构体的对齐整个结构体的对齐值⼀般是结构体中最⼤数据类型所占的空间,⽐如下⾯这个结构体的对齐值就是8,因为double类型占8个字节。
struct Test2{int i ;double d ;};例⼦答案有了上⾯的基础,再回过头去看看⼀开始的两个例⼦先看结构体Test1 c是char类型,按1个字节对齐2 i是int类型,按四个字节对齐,所以在c和i之间实际上空了三个字节。
整个结构体⼀共是1 + 3(补齐)+ 4 = 8字节。
再看Test1i是int类型,按4字节对齐d是double类型,按8字节对齐,所以i和d之间空了4字节c是char类型,按1字节对齐。
所以整个结构体是 4(i) + 4(补齐)+ 8(d) + 1(c) = 17字节,注意!还没完,整个结构体还没有对齐,因为结构体中空间最⼤的类型是double,所以整个结构体按8字节对齐,那么最终结果就是17 + 7(补齐) = 24字节。
字节对齐和边界对齐介绍

字节对齐和边界对齐介绍⼀.什么是字节对齐,为什么要对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照⼀定的规则在空间上排列,⽽不是顺序的⼀个接⼀个的排放,这就是对齐。
对齐的作⽤和原因:各个硬件平台对存储空间的处理上有很⼤的不同。
⼀些平台对某些特定类型的数据只能从某些特定地址开始存取。
⽐如有些架构的CPU在访问⼀个没有进⾏对齐的变量的时候会发⽣错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进⾏对齐,会在存取效率上带来损失。
⽐如有些平台每次读都是从偶地址开始,如果⼀个int型(假设为32位系统)如果存放在偶地址开始的地⽅,那么⼀个读周期就可以读出这32bit,⽽如果存放在奇地址开始的地⽅,就需要2个读周期,并对两次读出的结果的⾼低字节进⾏拼凑才能得到该32bit数据。
显然在读取效率上下降很多。
⼆.字节对齐对程序的影响:先让我们看⼏个例⼦吧(32bit,x86环境,gcc编译器):设结构体如下定义:struct A{int 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字节。
之所以出现上⾯的结果是因为编译器要对数据成员在空间上进⾏对齐。
字节对齐算法

字节对齐算法
在计算机中,内存是以字节为单位进行分配和存储的。
字节对齐算法通过强制数据结构按照特定的字节对齐方式进行排列,从而减少内存碎片并提高内存访问效率。
字节对齐方式通常是将数据结构中的每个成员按照特定的字节对齐方式进行排列,以确保每个成员的内存地址都是特定的倍数。
例如,如果字节对齐方式是4,那么每个成员的内存地址都必须是4的倍数。
字节对齐算法可以应用于各种数据结构,包括变量、数组和结构体等。
它可以提高程序的性能和效率,并减少内存的浪费。
但是,过度的字节对齐可能会导致内存浪费和程序性能下降,因此需要权衡和优化。
总之,字节对齐算法是一种重要的内存优化技术,需要程序员在开发过程中加以应用和调整。
- 1 -。
结构体大小的计算用最简单的方法,通俗易懂的方法计算结构体大小

结构体⼤⼩的计算⽤最简单的⽅法,通俗易懂的⽅法计算结构体⼤⼩结构体计算要遵循字节对齐原则结构体默认的字节对齐⼀般满⾜三个准则:1) 结构体变量的⾸地址能够被其最宽基本类型成员的⼤⼩所整除;2) 结构体每个成员相对于结构体⾸地址的偏移量(offset)都是成员⼤⼩的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);3) 结构体的总⼤⼩为结构体最宽基本类型成员⼤⼩的整数倍,如有需要编译器会在最末⼀个成员之后加上填充字节(trailing padding)其实暂且不管这三原则,我的⽅法只要记住第三个,就是结构体⼤⼩结果要为成员中最⼤字节的整数倍先看下⾯定义的两个结构体.struct { char a; short b; char c; }S1;struct { char a; char b; short c; }S2;分别⽤程序测试得出sizeof(S1)=6 , sizeof(S2)=4注意为什么仅仅改变了结构体成员的顺序,结果不⼀样?解:(1)⾸先找出成员变量中最⼤的字节,可见对于S1和S2 最⼤是short ,占2个字节,(2)所以以后都已2个字节为准,也就是说最多只要2个字节,其他填充占位,注意下图⼀个格⼦表⽰⼀个字节,(3)所以先画2个格⼦,以后看成员顺序,逐次增加,每次⼀2为增加基准对于S1 ,来说,顺序是 char->short->char2个字节第⼀个char占⼀个字节多的这⼀个补0,只是占位作⽤short 刚好占2个字节第⼆个char也占1个多的这⼀个补0所以对于S1结构体⼤⼩为 2*3=6,⾄于为什么第⼆个char,多的那个字节不丢到,就是遵循第三个原则,就是结构体⼤⼩结果要为成员中最⼤字节的整数倍对于S2 嘛,也画个图,但是顺序是 char->char->short第⼀个char 占⼀个字节第⼆个char 占⼀个字节short 刚好占2个字节S2=2*2=4按照这个⽅法再看这样的⼀个结构体:struct stu1{int i;char c;int j;};很明显:最⼤字节为4个。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。
例如,想要获得S2中c的偏移量,方法为
size_tpos =offsetof(S2, c);// pos等于4
2)基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
structS5 { };
sizeof( S5 ); //结果为1
structS1
{
char c;
inti;
};
structS3
{
char c1;
S1 s;
char c2;
};
#pragmapack(pop) //恢复先前的pack设置
计算sizeof(S1)时,min(2,sizeof(i))的值为2,所以i的偏移量为2,加上sizeof(i)等于6,能够被2整除,所以整个S1的大小为6。
2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
对于上面的准则,有几点需要说明:
c1的偏移量为0,s的偏移量呢这时s是一个整体,它作为结构体变量也满足前面三个准则,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。
Why为什么受伤的总是我
请不要沮丧,我们来好好琢磨一下sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况:
S1s1= { 'a', 0xFFFFFFFF };
定义上面的变量后,加上断点,运行程序,观察s1所在的内存,你发现了什么
以我的VC6.0为例,s1的地址为0x0012FF78,其数据内容如下:
}
结构体的sizeof
这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:
structS1
{
char c;
inti;
};
问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。
0012FF78: 61CCCCCCFFFFFFFF
发现了什么怎么中间夹杂了3个字节的CC看看MSDN上的说明:
When applied to a structure type or variable,sizeofreturns the actual size, which may include padding bytes inserted for alignment.
通过上面的叙述,我们可以得到一个公式:
结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目,即:
sizeof(struct) =offsetof( last item ) +sizeof( last item ) +sizeof( trailing padding )
到这里,朋友们应该对结构体的sizeof有了一个全新的认识,但不要高兴得太早,有一个影响sizeof的重要参量还未被提及,那便是编译器的pack指令。它是用来调整结构体对齐方式的,不同编译器名称和用法略有不同,VC6中通过#pragmapack实现,也可以直接修改/Zp编译开关。#pragmapack的基本用法为:#pragmapack( n ),n为字节对齐数,其取值为1、2、4、8、16,默认是8,如果这个值比结构体成员的sizeof值小,那么
同样,对于sizeof(S3),s的偏移量为2,c2的偏移量为8,加上sizeof(c2)等于9,不能被2整除,添加一个填充字节,所以sizeof(S3)等于10。
现在,朋友们可以轻松的出一口气了,:)
还有一点要注意,“空结构体”(不含数据成员)的大小不为0,而是1。试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。如下:
该成员的偏移量应该以此值为准,即是说,结构体成员的偏移量应该取二者的最小值,
公式如下:
offsetof( item ) = min( n,sizeof( item ) )
再看示例:
#pragmapack(push) //将当前pack设置压栈保存
#pragmapack(2) //必须在结构体定义之前使用让我们源自换一下S1中char与int的位置:
structS2
{
inti;
char c;
};
看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急,下面总结规律。
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
这里叙述起来有点拗口,思考起来也有点挠头,还是让我们看看例子吧(具体数值仍以VC6为例,以后不再说明):
structS3
{
char c1;
S1 s;
char c2;
};
S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,所以S3的最宽简单类型为int,这样,通过S3定义的变量,其存储空间首地址需要被4整除,整个sizeof(S3)的值也应该被4整除。
1)前面不是说结构体成员的地址是其大小的整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员的偏移量,这样思考起来简单。想想为什么。
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#defineoffsetof(s,m) (size_t)&(((s *)0)->m)
结构体字节对齐问题[转]
#include<stdio.h>
structa
{
char no[10];
intp;
longintpp;
unsignedintppp;
char x;
float y;
double h;
}xy;
void main()
{
printf("structa: %d \n",sizeof(structa)); //不是等于35吗???为什么等于40啦?