这两天在看结构体,一直在琢磨结构体的存储空间分配的问题,琢磨了半天总算明白了。和大家分享一下,希望能有所帮助。
相信大家都知道结构体里元素存储要对齐吧,话虽是没错,只是这个“对齐”里面包含了很多微妙的东西。首先详细的给出结构体内存存储空间分配的原则吧:编译器按照成员列表顺序一个接一个地给每个成员分配内存。只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。
而且还有3点要求:
结构体变量的首地址要能够被其最宽基本类型元素的大小所整除。
结构体的每个元素相对于结构体首地址的偏移量都是元素大小的整数倍,如有需要编译器会在元素之间加上填充字节。
结构体的总大小为结构体最宽基本类型元素大小的整数倍,如有需要编译器会在最末一个元素之后加上填充字节。
下面来看几个例子(32位为例):
sizeof操作符能够得出一个结构的整体长度,包括因边界对齐而跳过的那些字节。所以一般都用sizeof来计算其所占存储空间。
struct
t1
{
int a;
char b;
char
c;
};
首先创建的是int类型的a为4字节,但是其后一个b只占1个字节,所以不要和char
b对齐。因为其后一个c只占1个字节,所以也不用对齐。所以结构体t1一共占:4+1+1=6个字节,但是根据要求3,结构体的总大小为结构体最宽基本类型元素大小的整数倍。而在这个例子中,最宽的元素为int
a,为4字节。所以最后结构体t1的总大小必须为4的倍数,因此最终的字节数为8。所以,这里编译器自动充填了2字节的充填字节。
下面让我们将例1中元素的顺序调一下位置看看:
struct
t2
{
char b;
int a;
char
c;
};
计算后可以得到t2总字节数为12。是不是很疑惑,为什么就是位置换了一下结果会有所不同呢?这就是前面定义中所说的顺序的问题。来分析一下,首先创建的是
char b为1字节,然后是 int a为4字节,要对齐,所以应该在b后添加3个字节创建 int a,因为最后的cahr
c只占1字节,所以不用充填,所以总字节数为:4+4+1=9,还是因为要求3,应该为4的倍数,所以总字节为12(3个充填字节)。
那么加上数组呢?来看看吧。
struct
t3
{
int a;
char b[9];
char c;
};
分析:a占4个字节,b和c分别占9个字节和1个字节,加起来10个字节,但是因为要求3,这里最宽的元素为int,所以要为4的倍数,所以总共需要16个字节。
再掉一下位置吧.
struct
t4
{
char b[9];
int a;
char c;
};
分析:b占9字节,a占4字节,为了对齐,这时候应该是12(9+3,因为char
比int少3字节,所以为了对齐要加上那3字节)+4个字节,后面又来一个c
也是char,为了对齐加4(1+3),所以总共是20个字节。而t3因为后面两个元素类型一致,所以可以先和在一起分配,然后对齐。
所以可以知道,要不要对齐是看基本元素类型的,比如虽然char
b[9]比int
a占的字节要多,但是因为基本元素类型不一样,所以还是要对齐。
PS:打了将近一个小时的字,手都酸死了。
文章来源:Shura
本文地址:C语言
结构体存储空间分配
本文作者 : Shura
C语言 结构体存储空间分配
时间: 2024-11-03 21:57:22
C语言 结构体存储空间分配的相关文章
C语言结构体声明中冒号的使用(占位符) &; C结构体的乱序初始化
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为"位域"或"位段".所谓"位域"是把一个字节中的二进位划分为几 个不同的区域,并说明每个区域的位数.每个域有一个域名,允许在程序中按域名进行操作.这样就可以把几个不同的对象用一个字节的二进制位域来表示.一.位 域的定义和位域变量的说明位域定义与
C语言结构体(struct)常见使用方法
基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 [cpp] view plain copy struct stuff{ char job[20]; int age; float height; }; 第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义 [cpp] view plain copy //直接带变量名Huqinwei st
解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久.其实相关的文章很多,感觉说清楚的不多.结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1.数据成员对齐规则:结构(struct或
strcut的用法--------C语言结构体(struct)常见使用方法(转载)
今天复习一下struct,顺便挖掘一下以前没注意的小细节: 基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 [cpp] view plain copy struct stuff{ char job[20]; int age; float height; }; 第二种:附加该结构体类型的"结构体变量"的初始化的结构体定义 [cpp]
Go语言结构体(struct)
Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性: title :书名 author :作者 address :地址 mobile :手机号 publisher :出版社 定义结构体 结构体定义需要使用 type 和 struct 语句.struct 语句定义一个
C语言 结构体指针赋值 incompatible types when assigning to type 'char[20]' from type 'char *'
strcpy(pstudent->name, "guo zhao wei "); 为什么错误,该怎么写,(红色行) 追问 为什么不能直接赋值啊, 追答 用char nnnn[20]定义的,用strcpy 用char *ppp定义的,用=来赋值 C语言 结构体指针赋值 incompatible types when assigning to type 'char[20]' from type 'char *'
漫谈C语言结构体struct、公用体union空间占用
先用代码说话: #include<stdio.h> union union_data0{ int a ;//本身占用4个字节 char b ;//本身占用1个字节 int c ; }; union union_data1{ short a;//本身占用2个字节 char b[13];//本身占用13个字节 int c ;//本身占用4个字节 }; struct struct_data{ int a ;//int本身占用4个字节,偏移量为0 char b ;//char本身占用1个字节,偏移量为
C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用
C语言结构体,C语言结构体指针,java对象引用,传值,传地址,传引用 传值 把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 传地址 传值的一种特殊方式,只是他传递的是地址,不是普通的如int 那么传地址以后,实参和行参都指向同一个对象 传引用 真正的以地址的方式传递参数 传递以后,行参和实参都是同一个对象,只是他们名字不同而已 对行参的修改将影响实参的值 所谓变量是内存地址的一个抽象名字,在静态编译的程序中,所有变量名都会在编译时转换成内存地址,机器不知道变量名,只知道地址. C 语
C语言结构体(struct)常见使用方法(转)
本文转自 CSDN huqinweI987 基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 [cpp] view plaincopy struct stuff{ char job[20]; int age; float height; }; 第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义 [cpp] view plaincopy