结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。...对于结构体的字节对齐主要有下面两点: 1)结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数(这句话中的对齐参数是 取每个变量自身对齐参数和系统默认对齐参数#pragma pack...从上面可以发现,在windows(32)/VC6.0下各种类型的变量的自身对齐参数就是该类型变量所占字节数的大小,而在 linux(32)/GCC下double类型的变量自身对齐参数是4,是因为linux...此时结构体所占的字节数为1+3+4+2=10字节 最后由于a,b,c的最终对齐参数分别为1,4,2,最大为4,#pragma pack(n)的默认值为8,则结构体变量最后的大小必须能被4整除。...对于整个结构体来说,各个变量的最终对齐参数为1,4,8,4,最大值为8,#pragma pack(n)默认值为8,所以最终结构体的大小必须是8的倍数,因此需要在最后面填充4字节达到32字节。
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。...1)结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数的整数倍,如有需要会在成员之间填充字节。...从上面可以发现,在windows(32)/VC6.0下各种类型的变量的自身对齐参数就是该类型变量所占字节数的大小,而在linux(32)/GCC下double类型的变量自身对齐参数是4,是因为linux...此时结构体所占的字节数为1+3+4+2=10字节 最后由于a,b,c的最终对齐参数分别为1,4,2,最大为4,#pragma pack(n)的默认值为8,则结构体变量最后的大小必须能被4整除。...对于整个结构体来说,各个变量的最终对齐参数为1,4,8,4,最大值为8,#pragma pack(n)默认值为8,所以最终结构体的大小必须是8的倍数,因此需要在最后面填充4字节达到32字节。
结构体字节对齐 结构体的空间大小: 结构体为了保证CPU的访问效率,默认采用内存对齐机制 对齐标准为结构体中基础数据类型的成员最大值 对齐标准和成员申明顺序有关 #include #...我们可以将其理解为结构体成员会按照特定的规则来存储数据内容。 通过上图我发现结构体的存储不是简单的字节的累加:4+16 = 20;4+15 = 20; 2.为什么要使用字节对齐规则呢?...(2)从第二个成员开始,在其自身对齐数的整数倍开始存储(对齐数=编译器默认对齐数和成员字节大小的最小值,VS编译器默认对齐数为8)。 (3)结构体变量所用总空间大小是成员中最大对齐数的整数倍。...(4)当遇到嵌套结构体的情况,嵌套结构体对齐到其自身成员最大对齐数的整数倍,结构体的大小为当下成员最大对齐数的整数倍。...结构体的偏移量:某一个成员的实际地址和结构体首地址之间的距离。 结构体字节对齐:每个成员相对于结构体首地址的偏移量都得是当前成员所占内存大小的整数倍,如果不是会在成员前面加填充字节。
1.什么是字节对齐 在c语言的结构体里面一般会按照某种规则去进行字节对齐。...从以上结果可以看出,结构体st1在32位下是按照4个字节来对齐的,在64位下则是按照8个字节来对齐的,结构体st2则不管32位还是64位则都是按照1个字节对齐的。...那么我们可以总结出对齐规则如下: 在所有结构体成员的字节长度都没有超出操作系统基本字节单位(32位操作系统是4,64位操作系统是8)的情况下,按照结构体中字节最大的变量长度来对齐; 若结构体中某个变量字节超出操作系统基本字节单位...3.手动设置对齐 什么情况下需要手动设置对齐: 设计不同CPU下的通信协议,比如两台服务器之间进行网络通信,共用一个结构体时,需要手动设置对齐规则,确保两边结构体长度一直; 编写硬件驱动程序时寄存器的结构...//这里计算sizeof(st3)=5 4.结构体比较方法 可以使用内存比较函数memcpy进行结构体比较,但因为结构体对齐可能会有填充位不一致的情况,此时需要注意: 设置为1个字节对齐,使它没有空位
前面是整齐的后面就整齐 前面站的错开了 后面就跟着都错开了 数起来还不好数;说白了,一个正确的字节对齐方式,就是为了让CPU在最短的时间内读取完变量,同时还让整体的结构存储空间最小。...详细我们下面再介绍 对齐规则 1)结构体总长度; 2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置; 细分步骤: 1.确定结构体第一个结构体变量位于结构体0偏移的位置 2.对齐其他成员变量通过对齐数...对齐数就是编译器默认的一个对齐数与该结构体中的成员变量大小中的较小值 3.结构图总大小是最大对齐数的整数倍(成员、结构体都有自己的对齐数) 虽然到目前为止你也没看懂我写的是什么,但下面我将详细介绍对齐数...//对齐数 = 2 有效对齐数min(2,4); 然后我们再看结构体的对齐数 因为成员基本类型对齐数 最大是4 所以该结构体的对齐值是4 min(4,4) 所以该结构体的有效对齐值是4 那我们现在就把这个结构体对齐...= 0; 总长度就是我们结构体对齐之后的长度 实际对齐长度就是结构体的有效对齐值 选择最好的对齐字节数值 如何选择最好的对齐数值 设置不同的字节对齐方式对于数据的存储空间来说有不同的影响,在和变量自身对齐值为整数数关系下
前言: 大家在学习结构体中,在计算结构体大小时想必会很疑惑,为什么结构体的大小不是按照常理像数组一样一个字节一个字节的挨在一起放?今天带大家一起深入探讨一下背后的规则和原因。...结构体对齐规则: 结构体对齐其实就是所有成员变量都要对齐到对齐数整数倍的地址处 首先认识一下默认对齐数的概念,每个编译器都有默认对齐数,我这里使用的是vs2022,它的默认对齐数是8。 ...第二个对齐数是1,任何位置都是1的整数倍,所以直接接在a的后面1个字节,但最后结构体的大小可不是5 因为要满足结构体总大小是最大对齐数的整数倍,此时最大对齐数是4,5不是4的整数倍,8才是4的整数倍,...第一个变量跟刚才一样,任何位置都是1的整数倍,所以直接放在0号位 第二个变量对齐数为4,不能直接接在第一个变量后面,因为要对齐到对齐数整数倍位置,所以要从第四个字节开始放,如下图: 、 所以这个结构体的大小也是...注意如果结构体里面嵌套了结构体,那么嵌套在里面的结构体对齐数是: 该结构体的最大对齐数。 如下图所示: 为什么要结构体对齐? 从上面的例子不难看出,结构体对齐是会浪费空间的,可是为什么要这样做呢?
对齐原则 原则A:struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始位置必须是当前成员大小的整数倍 原则B:如果结构体A含有结构体成员B,那么B的起始位置必须是B中最大元素大小整数倍地址...(相当于先将嵌套结构体展开) 原则C:结构体的总大小,必须是内部最大成员的整数倍 示例 代码 struct A { int a; char b; char c; }; struct
1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处。 2.其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处。...对齐数=编译器默认的一个对齐数与该成员大小的较小值。(VS中默认的对齐数是8) 3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数 )的整数倍。...4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。...2.性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。...总的来说: 结构体的内存对齐是拿空间来换取时间的做法 既然这样,那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:让占用空间小的成员尽量集中在一起。
一、什么是结构体对齐?...其实就是c语言结构体对齐搞的鬼 二、为什么会这样子?...三、结构体对齐的好处 3.1 cpu读取一次能读取多少数据? 要看数据总线是多少位,如果是32位,则可以读取4个字节,如果是64位,则可以读取8个字节,并且cpu不能跨内存区间访问。...3.2 提升读取效率 结构体对齐的好处就是一次cpu的读取数据就可以完成一个变量的读取。...这样子不就是浪费时间了吗,所以结构体对齐就是一种空间换时间的方式。 ? 四、总结 以后写结构体一定注意结构体对齐问题,结构体会因为成员不同的排列顺序,产生不同大小的内存占用。
这就是因为结构体类型的变量在开辟内存的时候,要遵循结构体内存对齐,只有对齐到符合的地址处时,才会开始为成员分配内存 在了解如何对齐前,我们先来了解对齐数这个概念 ① 一个变量的对齐数 = 编译器默认的对齐数...与 该成员变量大小之间的较小值 ②如果嵌套了结构体类型的成员,则这个成员的对齐数就是 这个嵌套的结构体的自身成员中的最大对齐数 ●VS中默认的对齐数是8 ●Linux中gcc没有默认对齐数(即对齐数就是成员变量的自身大小...) 接下来我们就来介绍一下结构体内存对齐的规则: 1,结构体的第一个成员对齐到与结构体变量起始位置的偏移量为0的地址处(简单来说就是第一个成员变量的内存从起始位置开始分配) 2,其他成员变量要对齐到...与起始位置的偏移量为这个变量的对齐数的整数倍的地址处,然后再开始分配内存 3,结构体的总大小应该为 所有成员中最大对齐数 的整数倍 2,例子分析 我们计算结构体的大小的一般流程如下 了解了上面的知识以后...birthday的对齐数 2,birthday成员的大小,birthday也是一个结构体,也要用结构体内存对齐的方式来计算大小 具体分配如下: 二,结构体数组 1,什么是结构体数组 结构体数组,
设结构体如下定义: struct A { int a; char b; short c; }; 结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的...结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解)。这样就不难理解上面的几个例子的值了。...再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求, 0x0009到0x0000=10字节,(10+2)%4=0。...这里主要看结果中struct s1和struct s2结构体的大小及struct s2中成员c的地址,可以得出一下结论(gcc版本4.1): 1 Linux 64位系统下gcc编译器默认对齐为8字节...2 Linux32位系统下gcc编译器默认对齐为4字节 3 在64位系统#pragma pack(4)的情况下,a1->c的地址按4字节对齐而不是按8字节(long在64位下为8字节长),会不会影响
前言: 结构体的内存对齐是有关结构体内容的很重要一个知识点,主要考察方式是计算结构体的字节大小。...如图所示,根据offsetof我们可以得到这样的内存存储模式,但是这样一共也就9个字节,后面的3个字节从何而来?中间多出来的3个字节又从何而来? 我们继续探索。 结构体到底如何计算?...三、总结计算方法 我们首先要知道结构体变量成员的自身字节大小,然后去寻找对齐数,对齐数的寻找方法就是将自身字节大小和默认对齐数比较,取较小值,这样先找到对齐数,然后根据自身的字节大小去填充,就完成了成员在内存中的存储...,右边是默认对齐数进行比较,最后再从对齐数中找出最大值,就是最大对齐数,所以最后0~15就是存储结构体的大小,也就是一共16个字节 练习二: struct S3 { double d; char...,结构体S3本身大小是16,需要对齐到自身最大对齐数的位置,也就是8,然后double类型的对齐数是8,最后总字节大小也满足最大对齐数,所以一共32个字节。
性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。...总体来说: 结构体的内存对齐是拿空间来换取时间的做法。 二.内存对齐规则 1. 第一个成员在与结构体变量偏移量为0的地址处。 2....结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。 4....如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 什么意思呢?...1中的一样,但顺序却不一样; 不过不用担心,他们内存对齐的规则还是一样的; vs2022 打印结果: 通过上面两个例子,我们发现,即使结构体的成员类型相同,结构体的内存大小最后可能还是不同,我们最好把小类型的写在一起
sizeof()计算结构体的大小 简要说明:结构体成员按照定义时的顺序依次存储在连续的内存空间,但是结构体的大小并不是 *** 简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统在存储结构体变量时的地址对齐问题...* 没有成员的结构体占用的空间是多少个字节 答案是:1个字节。...12 在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则: (1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) (2)结构体大小必须是所有成员大小的整数倍,...因此,编译器会在成员m后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。...由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。 对于嵌套的结构体,需要将其展开。
sizeof中来计算该结构体类型的大小: 可以看到,这个结构体的大小是32个字节。...这是由于int类型占用4个字节,char类型占用1个字节,float类型占用4个字节,而且结构体中的成员顺序是按照定义的顺序来排列的。...结构体中的成员变量有可能会存在空洞,即某些成员变量之间的字节没有被使用。 这是因为编译器为了保证结构体成员变量的地址是按照一定规则对齐的,会在成员变量之间插入一些空字节。...如果不进行内存对齐,那么这个结构体的大小应该是5个字节,但是由于int类型的地址必须是4的倍数,因此编译器会在char类型后面插入3个空字节,使得int类型的地址是4的倍数。...这样,结构体的大小就变成了8个字节,其中3个字节是空洞。
为了深入了解结构体的大小事如何计算的,即不得不了解结构体对齐。 结构体对齐 要想知道如何计算,就得先知道结构体对齐的规则: 第一个成员在与结构体变量偏移量为0的地址处。...如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。...按照结构体的对齐规则,可知结构体的第一个成员是从偏移量为0的地址处开始存储,因为c1的类型为char所以只占一个字节,而结构体的第二个成员是要对齐到对齐数的整数倍处,我们的先求出对齐数,按照结构体对齐的第二条规定...此时结构体的偏移量为9,而结构体的总大小为最大对齐数的整数倍,所以还得浪费三个字节空间才达到要求。所以struct s1的大小为12。...而整个结构体的大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍,此时结构体的偏移量为32正好是所有最大对齐数的整数倍。所以结构体的大小为32. 控制台的输出 为什么存在内存对齐?
1.2 内存对齐的规则 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。...VS 中默认的值为 8 Linux中 gcc 没有默认对齐数,对齐数就是成员自身的大小 结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。...如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对⻬数)的整数倍。...(注意本次解释的4仅针对本例,并不是每个结构体都是一样的,具体情况具体分析) 图解如下: 可以看到总共得到了9个字节的大小,但是还不是4的倍数,为此我们应该取到12字节的大小。...,得在三条规则的基础上,再多加一条规则:如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对⻬数)的整数倍。
uint8_t定义变量地址要1字节对齐。 uint16_t定义变量地址要2字节对齐。 uint32_t定义变量地址要4字节对齐。 uint64_t定义变量地址要8字节对齐。...四、结构体成员对齐问题: 首先明白一点,结构体里面的变量是什么类型,此变量的位置就是至少要几字节对齐,所以就存在结构体实际占用大小不是这些变量之和。...,a单字节对齐,b是两字节对齐,而c要是4字节对齐,从出现b定义完毕后空出来1个字节未被使用。...,b占用2字节对齐,c需要4字节对齐,这样就空出来2两个字节未使用,d占用8字节,最后一个a占用了8字节。...比如使用SDIO DMA从SD卡读取数据,我们就可以设置源地址依然是4字节对齐(外设访问要4字节对齐),而目的地址设置为字节对齐,就可以方便的解决4字节对齐问题。
以下我会举两个结构体的例子,分别画图的方式表达对齐的原则。 结构体对齐的公式 记住以下这些规则,把结构体往里面套就可以了。...结构体对齐的原则就是牺牲空间的方式来减少时间的消耗,空间用完还可以复用,而时间过去了就再也不会回来了。...以 #pragma pack(x) 中 x 的大小和结构中占用空间最大的成员做比较,取小值为 n(外对齐依据) 以 n 值和结构体每个成员比较,得出结果列表为 m[x] 根据每个成员的大小依次向内存中填充数据...,要求填充 成员的起始地址 减去 构体起始地址 的差都可以整除 m[x] ,如不能整除则向后移动,直到可以整除再填充成员到内存(内对齐依据) 当全部成员填充完毕后所占用的字节若不能整除 n,则扩充内存到可以整除...案例一 我们来看一个简单的案例,#pragma pack(4) 为 4,结构体中有 char、short、int 3个成员,其对齐的方式如下图表示: #include #pragma
整个结构体的长度必须能整除最长元素的字节数。 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。...在C99标准中,对于内存对齐的细节没有作过多的描述,具体的实现交由编译器去处理,所以在不同的编译环境下,内存对齐可能略有不同,但是对齐的最基本原则是一致的,对于结构体的字节对齐主要有下面两点: 1)结构体每个成员相对结构体首地址的偏移量...编译器在为结构体成员开辟空间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为对齐参数的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要求。...此时结构体所占的字节数为1+3+4+2=10字节 最后由于a,b,c的最终对齐参数分别为1,4,2,最大为4,#pragmapack(n)的默认值为8,则结构体变量最后的大小必须能被4整除。...对于整个结构体来说,各个变量的最终对齐参数为1,4,8,4,最大值为8,#pragma pack(n)默认值为8,所以最终结构体的大小必须是8的倍数,因此需要在最后面填充4字节达到32字节。
领取专属 10元无门槛券
手把手带您无忧上云