-
2019-03-22 15:16:40
1、什么是内存对齐?
下面先来看一个例子:
#include <stdio.h> int main() { struct Text1 { char c1; short s; char c2; int i; }; struct Text2 { char c1; char c2; short s; int i; }; printf("%ld\n",sizeof(struct Text1)); //12 GCC下编译的结果 printf("%ld\n",sizeof(struct Text2)); //8 return 0; }
解析:
在windows系统32位平台上:
int占4个字节
char占1个字节
float占4个字节
double占8个字节
1、首先确定对齐参数:对齐参数是由变量的自身对齐参数和编译器默认的对齐参数一起确定的!它是结构体中所有变量的自身对齐参数的最大值和系统默认参数中较小的那一个!(含有double类型的除外,原因如下!)而变量的自身对齐参数是由CPU字节长度(32位为4)和变量本身的字节长度中的较小的那一个(即变量的自身对齐参数<=4),所以本题中的对齐参数为4!
2、知道了对齐参数为4,即知道了分配单位就是4!
这里需注意的是:
VC和GCC默认的都是4字节对齐,编程中可以使用#pragma pack(n)指定对齐模数。出现以上差异的原因在于,VC和GCC中对于double类型的对齐方式不同。
Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则: 任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型(8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。
Linux下的GCC奉行的是另外一套规则:任何2字节大小(包括单字节吗?)的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数!#prama pack()能改变编译器的默认对齐方式!例如
#pragma pack(n) //编译器将按照n字节对齐 #pragma pack() //编译器将取消自定义字节对齐方式
在#pragma pack(n)和#pragma pack()之间的代码按n字节对齐! 此为强制对齐!
2、为什么会有内存对齐?
字、双字和四字在自然边界上不需要在内存中对齐。对字、双字和四字来说,自然边界分别是偶数地址、可以被4整除的地址和可以被8整除的地址。无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;然而,对齐的内存访问仅需要进行一次访问。
一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问中未对齐的数据。
补充:
自然对齐指的是将对应变量类型存入对应地址值的内存空间,即数据要根据其数据类型存放到以其数据类型为倍数的地址处。例如char类型占1个字节空间,1的倍数是所有数,因此可以放置在任何允许地址处,而int类型占4个字节空间,以4为倍数的地址就有0,4,8等。编译器会优先按照自然对齐进行数据地址分配更多相关内容 -
有朋友问:结构体变量n所占内存字节数是?
2018-12-31 08:18:081.下列程序中,结构体变量n所占内存字节数是(答案为6?) union U { char s[4]; int i; long l; }; struct A { int c; union U u; }a; 2.若有下面的说明和定于: struct test { int m1;...有朋友问:
1.下列程序中,结构体变量n所占内存字节数是(答案为6?)union U
{
char s[4];
int i;
long l;
};
struct A
{
int c;
union U u;
}a;
2.若有下面的说明和定于:
struct test
{
int m1;char m2;float m3;
union uu{ char u1[5];int u2[2];} ua;
}myaa;
则sizeof(struct test)的值是(答案为12?)
3.在16位的PC机上使用c语言,若有如下定义:
struct data
{
int i;
char ch;
double f;
}b;
则结构变量b占用内存的字节数是(答案为11?)
答复:
如果你这是考试用题,建议你采用这个方式来计算:
1、假设是在16位IBM-PC机上计算所占用内存的字节数,决定了各类型的宽度;
2、union(共用体)变量的所占用内存的字节数为变量类型定义的变量的最大宽度变量;
3、如果有数组要考虑数组的宽度(比如char[3]肯定小于int[2],cha[5]就按5个字节算,因为大于了int[2]);
4、结构体变量所占用内存的字节数是其所有成员所占用内存字节数之和;
5、结构体里有结构体也要按照上面的方法计算。
那么,由于假设16位IBM-PC机,所以:
char:1字节、short:2字节、int:2字节、long:4字节、long long(即long long int):4字节、float:4字节、double:8字节、long doubule:10字节
这样你就好计算了:
题目1:union U u; u的宽度为最大char s[4];的4个字节,int c;2个字节。所以结果为6个字节。
题目2、题目3你自己应该就会算了吧?
有个问题还是要补充一下,在现在我们用的IDE在实际环境中,由于为了实现更快寻址和达到性能更优的原因,会有本机宽度和字节对齐的情况发生,所以你在你具体应用中会有一些不同情况的出现。另外,long double占用10字节空间,但有的编译器并不认可10字节,还是8字节,比如在VC++6.0下,用sizeof(long double)测出来的值仍然是8。所以我强调了第1点假设是在16位IBM-PC机上,而且估计你提的这几个问题都是考试用的,所以就按我上面说的方法去计算就可以。 -
判断结构体变量所占字节数
2018-07-29 21:19:141,结构体总长度一定是最长字节数的整数倍,double除外,若出现double还是除它之外的最大类型的字节数的整数倍,double还是按8字节算 2,每个成员偏移量一定是改成员长度的整数倍 eg #include <stdio.h&...规则
1,结构体总长度一定是最长字节数的整数倍,double除外,若出现double还是除它之外的最大类型的字节数的整数倍,double还是按8字节算
2,每个成员偏移量一定是改成员长度的整数倍
eg
#include <stdio.h> struct student { char name[20]; int a; short b; }; int main() { printf("%d\n", sizeof(struct student)); return 0; }
嵌套结构体所占字节数示例
#include <stdio.h> #include <string.h> #include <stdlib.h> struct AA { int a; char b; }; struct student { short c; struct AA aa; char sex; }; int main() { printf("%d\n", sizeof(struct student)); return 0; }
说明:
1,struct AA aa,占8个字节; 然后将其整体带入struct student{....}结构体中, short 补两个字节 4+8+1=13, 需要再补三个字节使其为4的倍数
-
结构体所占内存的字节数如何计算?
2019-08-22 21:43:23处理器的对齐要求,可能会在较小的成员后加入补位,从而导致结构体实际所占内存的 字节数比我们想象的多出一些字节。 下面从4个方面进行阐述: (1)结构体只包含基本数据类型; (2)结构体含有复合...我们知道,为了提高内存寻址的效率,很多处理器体系结构为特定的数据类型引入 了特殊的内存对齐需求。不同的系统和编译器,内存对齐的方式有所不同,为了满足 处理器的对齐要求,可能会在较小的成员后加入补位,从而导致结构体实际所占内存的 字节数比我们想象的多出一些字节。
下面从4个方面进行阐述: (1)结构体只包含基本数据类型; (2)结构体含有复合数据类型(例如包含strcut,union); (3)空结构体; (4)结构体含位域。
下面的例子均在VS平台测试,不同平台实现可能有差异。
1.结构体只包含基本数据类型:
规律总结(按字节编址):1.从0位置开始存储; 2.short类型数据要求从偶数地址开始存储; 3.int数据要求对齐在4字节地址边界; 4.变量存储起始位置是该变量大小的整数倍; 5.结构体总的大小是其最大元素的整数倍,不足的后面补齐; 6.结构体变量的首地址能够被其最宽基本数据类型成员的大小整除;
例子1:
struct Test { int num;//0 1 2 3 占4个字节 char *pname;//4 5 6 7 占4个字节 short date;//8 9 占两个字节 char ch[2];//10 11 占两个字节 short sh[4];//12 13 14 15 16 17 18 19 占8个字节 满足上面的规律5 }; 4+4+2*2+8=20 满足上面的5条规律 故sizeof(struct Test)=20
例子2:
struct Test { char c;//0 1 2 3 占4个字节(补3个字节,因为int占4个字节,需满足规律4) int a;// 4 5 6 7 占4个字节 short s;//8 9 10 11 占4个字节(补两个字节,因为int占4个字节,需满足规律5) }; 4*3=12 故sizeof(struct Test)=12
例子3:
struct Test { int a;//0 1 2 3 占4个字节 char b;//4 5 占两个字节(补1个字节,因为short占两个字节,需满足规律4) short c;//6 7 占两个字节 }; 4+2+2=8 故sizeof(struct Test)=8
2.结构体含有复合数据类型:
规律:1.在寻找最宽基本类型成员时,应当包括复合类型成员的子成员, 而不是把复合成员看成是一个整体; 2.在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
例子1:
struct s1 { char c;//0 1 2 3 占4个字节 int b;//4 5 6 7 占4个字节 }; //s1结构体共占8个字节 struct s2 { char c1;//0 1 2 3 占4个字节 struct s1 s;//4-11 占8个字节 char c2;//12-15 占4个字节 }; 故sizeof(struct s2)=16个字节
说明:s1最宽简单成员的类型为int,s2在考虑最宽简单类型成员时是将s1“打散”看的,所以s2的最宽基本类型为int,这样,通过s1定义的变量,其存储空间的首地址应该被4整除(上面的规律6),整个sizeof(s2)的值也应该被4整除(规律5)。c1的偏移量为0,s的偏移量呢,这时s是一个整体,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。
例子2:
union u1 { char bj[5]; int bh; }; //共用体类型所占内存空间的大小取决于其成员中占内存空间最多的那个成员变量。 //故为字符数组这个成员变量,同样,整个共用体所占的内存字节数应为最宽数据类型的整数倍, //需在后面补3个字节,即:sizeof(union u1)=8。 struct s { union u1 { char bj[5]; int bh; }; char c[8]; float f; };
说明:整个共用体共占8字节内存空间,即:0-7,字符数组占8个字节内存空间,即:8-15,float类型占4个字节内存空间,即:16-19。故,sizeof(struct s)=20。
例子3:
union u1 { char bj[5]; int bh; }; struct s { union u1 { char bj[5]; int bh; }; char c[7]; };
说明:整个共用体共占8个字节内存空间,即:0-7,字符数组占7个字节内存空间,即8-14,这时,我们同样也需要将共用体“打散”看,结构体最宽基本数据类型为int,故整个结构体所占字节数为16(需在最后补1个字节,满足规律5),即:sizeof(struct s)=16。
3.空结构体:
空结构体(不含数据成员)的大小不为0,而是1。试想一个“不占空间”的变量如何被取地址, 两个不同的“空结构体”变量又如何得以区分呢?于是,“空结构体”变量也得被存储, 这样编译器也就只能为其分配一个字节的空间用于占位了。
4.结构体含位域:
C99规定,int、unsigned int和bool可以作为位域类型,但编译器几乎都对此做了拓展,允许 其他类型的存在。使用位域的主要目的是压缩存储。 规律: 1.如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前 一个字段存储,直到不能容纳为止; 2.如果相邻位于字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的 存储单元开始,其偏移量为其类型大小的整数倍; 3.如果相邻的位域字段的类型不同,其各编译器的具体实现有差异,VS采取不压缩方式; 4.如果位域字段之间穿插着非位域字段,则不进行压缩; 5.整个结构体的总大小为最宽基本类型成员大小的整数倍。
例子1:
struct s1 { char c1:3; char c2:4; char c3:5; };
其内存布局:
| —c1---- | ----c2------ | _ |-------c3---------|------------|
| _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ |
位域类型为char,第1个字节仅能容下c1和c2,所以c2被压缩到第1个字节中(规律1),而c3只能从下一个字节开始(规律2)。所以sizeof(struct s1)=2。例子2:
strcut s2 { char c1:3; short s1:4; char c2:5; };
由于相邻位域类型不同,在VS中不采取压缩方式,故c1占1个字节,由于s1为short类型,故c1补一个字节。s1占两个字节,c2占一个字节,再补一个字节。故sizeof(struct s2)=6。
例子3:
struct s3 { char c1:3; char c2; char c3:5; };
由于非位域字段穿插在其中,不会产生压缩。故sizeof(struct s3)=3。
-
2021.12.6 用结构体定义的变量所占字节(应用)
2021-12-06 18:10:54(2) 结构体变量中每一个成员 相对于结构体首地址的偏移 一定是该成员的基础数据类型大小的整数倍 (3) 结构体变量的总大小 一定是这个结构体变量中 最大的基础类型的大小的整数倍 1. 看如下的结构体,其所占字节为... -
C语言-结构体struct所占字节数计算
2021-11-24 10:20:08从C语言设计准测角度理解结构体所占字节数。 -
C语言结构体,共用体所占字节数计算
2022-03-28 11:14:50字节数: 环境 char short int long long long ...(无符号型在原来的基础上不变,例如 ...第二条原则:结构体变量所占空间的大小是对齐参数的整数倍。 结构体 结构体所占内存的长度是各成员占得内存长度之和。 例 -
02内存对齐之结构体在内存所占字节数求法(学会这篇所有内存对齐面试题基本可以解决)
2020-08-01 22:37:0502内存对齐之结构体在内存所占字节数求法 1 结构体在内存所占字节数求法,需按成员类型划分来求 1)简单类型(即结构体没有内嵌结构体): 先求出总内存: 成员1类型所占字节数 x (0~n); 成员2类型所占字节数 x (0~n);... -
共用体union与结构体struct所占内存字节大小
2021-04-27 19:08:08在***32位操作系统*里,结构体与共用体所占内存字节大小严格遵从字节对齐(每四个字节对齐,为了方便,下文称四字节大小空间,理解时将四个字节空间看成一个整体) 如图,内存以字节存储,顺序存储 stu1,依次存储,... -
如何计算结构体所占字节大小
2022-04-03 13:34:51在此之前需要引入一个对齐数的概念:对齐数=min较小值(该成员大小,编译器默认对齐数),vs编译器默认为8。如果没有默认对齐数,对齐数=该成员大小。 如 int a的对齐数就等于4,char b=1,double c=8; 二、偏移量 在... -
结构体成员所占内存中的地址(另一个字节占一个地址)
2021-04-09 17:34:25一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。 例一: #include <iostream> using namespace std; struct X { -
【C/C++】一个结构体变量占多大内存空间的问题
2018-10-24 11:25:26原文链接:... 一个结构体变量占多大内存空间的问题 直接来看相同数据结构体的几种书写的格式吧。 格式一: 1. struct tagPhone 2. { 3. char A; 4. int B; 5. ... -
C语言 - 结构体所占字节数
2018-07-04 11:57:35在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际... -
关于结构体中各个变量在内存中所占空间
2020-03-12 13:05:39} 我们不妨假设这两个结构体所占内存字节数为其包含的各个变量所占字节数的代数和,那么,运行结果应该是1 + 4 + 8 和 1 + 8 + 4,也就是13 13。但是,最终我们得到的运行结果却是这样子的: 这就不得不提到计算机... -
【C语言】结构体占用字节数及存储与空间分配
2021-05-19 08:09:17在计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取决于结构体中最大基本类型的大小,下面我们看几个例子:1.struct A{char a;int b;short c;}str1;这里char占1个字节,int占... -
C语言中结构体变量到底占多大空间
2018-09-07 21:56:30很久之前就想将内存对齐这块儿知识点总结记录下来,无奈本人患有very very严重的拖拉症,直到今天才下... 结构体到底占多大的空间呢?先看一下下面这道题的输出结果: #include<stdio.h> typed... -
C 语言中结构体中成员所占内存的大小
2020-10-20 23:01:22结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数的整 数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为对齐参数的整数... -
struct结构体占内存字节数
2020-03-20 10:01:18昨天写了一个结构体demo,心血来潮打印struct所占内存字节数 struct student{ char name[20]; char sex; int num; float score[3]; void print(); }; 你猜猜是多少个字节数呢(对于char[]这样的赋值,先暂且... -
结构体占多少字节
2021-03-09 15:28:33结构体的数据类型的有点多我们就不啰嗦了,直接来看相同数据结构体的几种书写的格式吧。 格式一: 1 2 3 4 5 6 01.struct tagPhone 02.{ 03. char A; 04. int B; 05. short C; 06.}Phone; 格式二: 1 2 3 4 5 6 01... -
C++ 结构体所占字节数
2017-09-06 12:13:27在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上... -
c语言结构体struct所占字节数求解
2018-10-27 15:24:25原本觉的c语言学的还不错,今天看了一下c语言的有关书籍,看到求结构体大小的例子,心想这不是很简单吗,不就是把所有成员的大小...这个结构体的大小是多少了,我做的是char占1字节,int占4字节,short占2字节,1 +... -
结构体类型的字节数
2021-01-06 19:25:20sizeof()运算符用于计算基本类型、结构体类型的所占字节数; #include <iostream> using namespace std; struct student{ int id; char ch; }; int main() { printf("%d\n",sizeof(int)); printf("%d\n... -
struct 结构体 所占字节数的计算
2019-10-10 19:29:39定义结构体类型,只能说明该类型的组成情况,并没有分配内存空间。只有当定义属于结构体类型的变量时,系统才会分配空间给该变量。 -
c# sizeof() 计算结构体所占的字节 And 自定义结构体
2021-04-15 11:23:27namespace ConsoleApp1 { class ... // 获取自定义结构体的内存大小时 // 要放在unsafe上下文内 unsafe { int x6 = sizeof(Student); // 16 Console.WriteLine(x6); } } } struct Student { int ID; long Score; } } -
C++中结构体占几个字节的计算方法
2022-07-01 22:15:29C++中的结构体 -
一文搞懂结构体变量占用多大内存空间(详细)
2021-12-15 19:15:16请问下面定义的结构体变量aa在计算机内存中占用多少字节? #include main() { struct student { float height; short int age ; char sex ; }aa; printf("%d\n",sizeof(aa)); //屏幕上将显示多少? } 错误解答:... -
结构体内存对齐,结构体变量大小计算,位段内存分配及相关问题
2022-02-09 19:20:02结构体内存对齐,结构体变量大小计算,位段内存分配及相关问题 -
【C语言】结构体类型和结构体变量(字节对齐)
2020-10-19 22:22:33三、结构体变量的内存分配 四、结构体变量的初始化 五、结构体变量的引用 一、结构体类型定义 结构体是一种构造数据类型,可以把不同类型的数据整合在一起,每一个数据都称为该结构体类型的成员。使用结构体时,... -
C语言计算结构体所占的内存大小
2020-07-15 20:47:17用一道面试题题引入 struct str1 { char a; int b; float c; double d;...char类型占用1个字节,int型占用4个字节,short类型...在计算机中通常会让CPU从内存中一次读取若干个字节的数据,而不是一次只读取一个字节的数