首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么struct的大小不等于其各个成员类型的大小总和?

这个问题涉及到C语言中的数据结构,具体来说是关于struct的内存布局和对齐问题。struct是一种复合数据类型,它可以将不同类型的数据组合在一起,以便在一个单独的变量中存储多个值。

在C语言中,struct的大小不等于其各个成员类型的大小总和,这是因为编译器会对struct进行内存对齐,以提高程序的运行效率。内存对齐是指在分配内存时,要求数据的起始地址必须是其类型大小的整数倍,这样可以使得程序访问数据时更快。

例如,假设有以下struct定义:

代码语言:c
复制
struct {
    char c;
    int i;
} s;

在这个struct中,char类型的大小通常是1字节,而int类型的大小通常是4字节。因此,我们可能会认为这个struct的大小应该是1字节加上4字节,即5字节。但是,实际上,这个struct的大小可能是8字节,因为编译器会对struct进行内存对齐,以确保int类型的变量i的起始地址是4字节的整数倍。

为了避免内存对齐导致的内存浪费,可以使用#pragma pack指令来控制struct的内存对齐方式。例如,可以使用以下代码来禁用内存对齐:

代码语言:c
复制
#pragma pack(1)
struct {
    char c;
    int i;
} s;
#pragma pack()

这样,struct的大小就会等于其各个成员类型的大小总和。但是,需要注意的是,禁用内存对齐可能会导致程序运行速度变慢,因此在实际开发中需要权衡利弊。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++:05---class和struct

,当用大括号对进行初始化需要注意: 当struct和class中都定义了构造函数,就不能使用大括号对进行初始化 若没有定义构造函数,struct可以使用{ }进行初始化,而只有当class所有数据成员及函数为...为什么不一样呢? struct为空结构体 表示占位为0字节,那么class为空sizeof意义呢: 一个类实例化对象所占空间大小?注意不要说类大小,是类对象大小....如果 Class A; A obj; 那么sizeof(A)==sizeof(obj) 那么sizeof(A)大小成员大小总和是什么关系呢,很简单,一个对象大小大于等于所有非静态成员大小总和。...基于上述两点,可以说用sizeof对类名操作,得到结果是该类对象在存储器中所占据字节大小,由于静态成员变量不在对象中存储,因此这个结果等于各非静态数据成员(不包括成员函数)总和加上编译器额外增加字节...后者依赖于不同编译器实现,C++标准对此不做任何保证。 C++标准规定类大小不为0,空类大小为1,当类不包含虚函数和非静态数据成员时,对象大小也为1。

68330

CC++刁钻问题各个击破之细说sizeof

(7)sizeof可以对函数调用求大小,并且求得大小等于返回类型大小,但是不执行函数体! (8)sizeof求得结构体(及其对象)大小不等于各个数据成员对象大小之和!...这个是为什么呢?我一时半会想不到,所以还请朋友们补充! 特性8:sizeof求得结构体(及其对象)大小不等于各个数据成员对象大小之和!...,为什么大小不一样呢?...要解释这个问题,就要了解结构体成员对齐规则,由于结构体成员对齐非常复杂,我将用专题——C/C++刁钻问题各个击破之位域和成员对齐——进行讲解,这里我只简单地介绍规则: 1、  结构体大小等于结构体内最大成员大小整数倍...2、  结构体内成员首地址相对于结构体首地址偏移量是类型大小整数倍,比如说double型成员相对于结构体首地址地址偏移量应该是8倍数。

75320

CC++基础之sizeof使用

向函数形参传递数组,数组将会退化为指针,失去原来数组特性。 4 结构体类型 sizeof 对于 struct 数据结构由 CPU 对齐问题导致 struct 大小变得比较复杂。...); // 输出8不是5 return 0; } 结构体大小跟结构体成员对齐有密切关系,而并非简单地等于各个成员大小之和!...; }; 结构体A和B中包含成员都一样,只不过顺序不同而已,为什么大小不一样呢?...结构体大小等于结构体内最大成员大小整数倍 结构体内成员首地址相对于结构体首地址偏移量是类型大小整数倍,比如说 double 型成员相对于结构体首地址地址偏移量应该是 8 倍数。...从三个规则我们来看看为什么 sizeof(B) 等于 24 :首先假设结构体首地址为0,第一个成员 num1 首地址是 0 (满足规则2),它类型是 int ,因此它占用地址空间 0——3 。

32730

C语言 | C++之sizeof使用

向函数形参传递数组,数组将会退化为指针,失去原来数组特性。 4 结构体类型 sizeof 对于 struct 数据结构由 CPU 对齐问题导致 struct 大小变得比较复杂。...); // 输出8不是5     return 0; } 结构体大小跟结构体成员对齐有密切关系,而并非简单地等于各个成员大小之和!...; }; 结构体A和B中包含成员都一样,只不过顺序不同而已,为什么大小不一样呢?...结构体大小等于结构体内最大成员大小整数倍 结构体内成员首地址相对于结构体首地址偏移量是类型大小整数倍,比如说 double 型成员相对于结构体首地址地址偏移量应该是 8 倍数。...从三个规则我们来看看为什么 sizeof(B) 等于 24 :首先假设结构体首地址为0,第一个成员 num1 首地址是 0 (满足规则2),它类型是 int ,因此它占用地址空间 0——3 。

2.4K88

内存对齐

、存储这个结构体起始地址是对齐边界整数倍 第一个成员a,它要对齐到1字节,而这里是相对地址0,所以直接放这里,然后是第二个成员b,它要对齐到8字节,但是接下来地址对8取模不等于0,所以要往后移。...所有成员放好还不算完,内存对齐第二个要求是结构体整体占用字节数需要是类型对齐边界整数倍,不够的话要往后扩张。所以要扩充到相当地址23这里。...最终这个结构体类型大小就是24字节 为啥要限制类型大小等于边界整数倍 ?...为什么?...地址对齐保证是:如果类型t对齐保证是n,那么类型t每个值地址在运行时必须是n倍数 零大小字段要避免只作为struct最后一个字段,会有内存浪费 参考 【Golang】这个内存对齐呀!?

63221

自定义类型:联合体和枚举类型(联合体与结构体区别)

: 结构体(struct):在内存中顺序存储包含所有成员。...每个成员都有独立内存空间。结构体大小是其所有成员大小总和,再加上可能内存对齐填充。 联合体(union):不同于结构体,联合体不是存储所有成员,而是使用相同内存空间来存储其所有成员。...联合体大小最大成员大小。在任何时候,联合体只保存最大成员值。 访问方式: 结构体(struct):可以同时访问其所有的成员。...联合大小至少是最大成员大小。...enum Color//颜色 { RED=2, GREEN=4, BLUE=8 }; 二、枚举类型优点​ 我们可以使用 #define 定义常量,为什么非要使用枚举?​

8310

结构体类型

内存中数据存放(额外要说点) 对于大小端存储模式只适用于单个数据(超过单个字节数据)里各个字节排列顺序,会使该数据各个字节都安排在对应地址上 (如在vs中最高位字节安排在最高地址处,最低位字节安排在最低地址处...node是不为结构体,所以struct由于存在一个不知道为什么类型node从而声明错误,自然也就替换不了,编译错误。...5.对于一个数组来说,数组对齐数=编译器默认一个对齐数与其成员类型大小,如int arr[40]对齐数就为 4....下面给一个例子 struct A { int a:2; int b:5; int c:10; int d:30; } struct A(位段)内存大小为多少,答案为8个字节。那么为什么呢?...这里还有个限制,我们数字不能超过数据类型比特位大小,如前面是int,则数字不能超过32,否则系统会错误。

5810

联合体类型和枚举类型

(有些人会认为联合体大小就是最大成员大小,但还会发生对齐,所以是至少是最大成员大小,如下举几个例子去证明联合体大小至少是最大成员大小) #include union Un1...printf("%d\n", sizeof(union Un1)); printf("%d\n", sizeof(union Un2)); return 0; } 数组对齐数是默认对齐数和成员类型大小较小值...(说了以上结论后想必推导出结果很简单,就不说结果推导) 而其最大成员大小分别为 5和14,但是联合体大小为 8 和16....对于联合体各个成员都是从联合体首个字节开始进行存储(像联合体这种包含多个数据类型内部都是从低地址到高地址进行存储,数组,结构体这种包含多个数据也是同理)。从而会共用同一块内存空间。...对测试得出一系列结论 一系列枚举类型如enum color等等本质其实是int 类型 ,因为类型大小为4个字节。

7610

【自定义类型:结构体,枚举,联合】

在这个结构体中,最大成员类型为int,占四个字节,故在9个字节基础之上我们还应该加上3个字节,即该结构体占用了12个字节大小。...所以接着第二个字节即可,第三个成员大小为int,占四个字节,4<8,故对齐数应该为4倍数,因此需要再跳过两个字节,在第五个字节开始开辟四个字节,故现在共占用了8个字节,8为最大对齐数4整数倍,故此结构体大小为...为什么存在内存对齐: 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上任意数据;某些硬件平台只能在某些地址处取某些特定类型数据,否则抛出硬件异常。...,总和47个比特位,看成48个比特位,就是6个字节大小,但是,这么单纯相加,也是不对。...计算方法如下: * 先看类型,int ,4个字节,32个比特位,因此,由于是int类型,我们先给4个字节大小,a,b,c一共用了2+5+10 = 17个比特位,而d占30个比特位,加上之后远远大于

45400

【c语言】详解结构体

在学习每个类型之前我们需要了解存在意义,即什么是结构体?为什么要引入结构体这个类型呢? 我们可以想象现实中我们是如何处理一个人信息?...在引入结构体这个类型后,我们想表示类似学生信息这样工作时,就会大大减少变量创建,也减少了我们工作量,提高了代码可读性。 结构体声明 上面解释了什么是结构体,为什么要引入结构体这个类型。...各个结构体成员初始值依次排列在{}里面,并用逗号进行分割。如果未赋初始值成员则被初始化为0。...VS中默认值为8 Linux中没有默认对齐数,对齐数就是成员自身大小 结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大整数倍。...));//---12 练习1分析: 变量 变量大小 默认对齐数 对齐数 c1 1 8 1 i 4 8 4 c2 1 8 1 通过上面表格,我们可以想象到在内存中存储大概: //练习2 struct

6510

【自定义类型详解】第二篇——结构体实现位段

位段,C语言允许在一个结构体中以位为单位来指定成员所占内存长度,这种以位为单位成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少位数存储数据。...如果成员全部是char类型,那就一次开辟1个字节空间,直至放得下所有成员。 好,那我想现在大家就明白为什么上面位段struct A大小是8个字节了。...struct S s1 = { 0 }; return 0; } 我们先来思考一下,s1 大小是多少,并猜测一下这些空间是如何分配给每个成员。...s1 每个成员都是char类型,所以应该每次开辟1个字节。...printf("%d", sizeof(s1)); return 0; } 我们先把位段变量s1 成员都赋值为0,然后给他们重新赋一个非0值,最后,我们借助编译器观察一下,各个成员再内存中存放是不是跟我们上面分析一样

9610

iOS—OC内存对齐原理

一、获取内存大小三种方式 1.1 sizeOf sizeof是一个操作符,不是函数 sizeof计算内存大小时,传入主要是对象或者数据类型,在编译器编译阶段大小就已经确定 sizeof计算出结果...一个指针大小为8字节 class_getInstanceSize 打印是内部成员变量大小 isa占8字节 name字符串8字节 age int类型 4字节 8+8+4=20 因为类成员变量按照...三、验证规则 1.1 各数据类型所占字节大小 1.2 创建两个不同结构体 myStuct1,myStruct2分别进行验证 code如下 struct myStruct1 { char a...,内存大小必须为结构体中最大成员8整数倍,32刚刚满足 四、内存优化 思考内存优化 接着上面的结论,我们思考下,为什么要内存对齐,其实苹果这么做目的让cpu读取内存效率更高,用空间换取时间。...16整数倍 总结: 对象大小成员变量类型和数量有关 对象实际内存是按照8字节对齐 对象分配内存大小按照16字节对齐。

49020

理解Golangnil

问题二:s是nil,v不是nil,为什么s还等于v?问题三:s.GetA()返回是nil,为什么nil还能继续调用GetA()方法?...= nil) // #=> true}这里和上面是相同问题,即返回nil为什么不等于nil?...其中_type起到至关重要作用,它是 Go 语言类型运行时表示。下面是运行时包中结构体,其中包含了很多类型元信息,例如:类型大小、哈希、对齐以及种类等。...{}定义和汇编结果我们可以发现:s整体堆栈是0,它和nil对比输出是trues确实是nil,但是v是有值,它拿到了一个Message类型地址v栈96位置s和v作比较对比是它们值(应该是成员变量...类型成员变量A值为0v在运行时是eface类型,其中成员变量data unsafe.Pointer指向s地址,成员变量_type *_type不为空,size,hash,equal都是有值,所以

54050

sizeof 知多少? (上)

很简单,对于只有单个成员结构,sizeof大小便是成员sizeof大小,拿s1来说: sizeof(s1) = sizeof(s1.m_1) = sizeof(int) = 4(字节) 那么如果...其实这里还有一个结构体连续存放问题 考虑结构体数组定义 S s[2],并且我们假设s起始地址是0,对于结构s[0]来说,各个成员都在对齐内存地址上,但是对于结构s[1]来讲,各个成员就未必在对齐内存地址上了...,我们再来计算一遍s2大小: 首先对齐各个成员(结构体对齐值是成员最大对齐值): sizeof’(s2, 0) = 0 sizeof’(s2, 1) = ceil(sizeof’(s2, 0)...由于联合体需要共用内存,所以其大小成员最大大小,再加上根据联合体对齐值进行填充数据大小(需要填充原因和结构体一致),而联合体对齐值则跟结构体一样,为成员最大对齐值 使用公式依然会更清晰一些...,指针类型sizeof大小为4字节,alignof大小也为4字节,在计算cv1内存大小时,我们仍然可以沿用之前计算公式: 首先对齐各个成员: sizeof’(cv1, 0) = 0 sizeof’

84700

sizeof 知多少?

很简单,对于只有单个成员结构,sizeof大小便是成员sizeof大小,拿s1来说: sizeof(s1) = sizeof(s1.m_1) = sizeof(int) = 4(字节) 那么如果...其实这里还有一个结构体连续存放问题 考虑结构体数组定义 S s[2],并且我们假设s起始地址是0,对于结构s[0]来说,各个成员都在对齐内存地址上,但是对于结构s[1]来讲,各个成员就未必在对齐内存地址上了...,我们再来计算一遍s2大小: 首先对齐各个成员(结构体对齐值是成员最大对齐值): sizeof’(s2, 0) = 0 sizeof’(s2, 1) = ceil(sizeof’(s2, 0)...由于联合体需要共用内存,所以其大小成员最大大小,再加上根据联合体对齐值进行填充数据大小(需要填充原因和结构体一致),而联合体对齐值则跟结构体一样,为成员最大对齐值 使用公式依然会更清晰一些...,指针类型sizeof大小为4字节,alignof大小也为4字节,在计算cv1内存大小时,我们仍然可以沿用之前计算公式: 首先对齐各个成员: sizeof’(cv1, 0) = 0 sizeof’

49400

自定义类型:结构体

1.结构体类型声明 1.1结构体概念 结构是一些值集合,这些值称为成员变量。结构每个成员可以是不同类型变量。...通过分析,我们可以发现这样代码其实是错误,因为一个结构体中再包含一个同类型结构体变量会使得结构体变量大小无穷大,很明显是不合理。...", .value = 30.5 }; //此时,library与library_2区别在于,前者时全局变量,后者时局部变量 //需要使用逗号分隔各个成员初始化 //为了提高代码可读性...对齐数=编译器默认一个对齐数 与 该成员变量大小较小值 ·VS中默认值为8 ·Linux中没有默认对齐数,对齐数就是成员自身大小 3.结构体总大小为最大对齐数...很显然是,第二种所占内存要小一点,所以我们要让占用空间小成员尽量集中在一起。 为什么存在内存对齐? 1.

8210

纠缠不清C语言位域(位段)详解

位域具体存储规则如下: 当相邻成员类型相同时,如果它们位宽之和小于类型 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们位宽之和大于类型 sizeof 大小,...那么后面的成员将从新存储单元开始,偏移量为类型大小整数倍。...sizeof(struct bs)大小之所以为 4,而不是 3,是因为要将内存对齐到 4 个字节,以便提高存取效率。...m 、ch、p 长度分别是 4、1、4 个字节,共计占用 9 个字节内存,为什么在 VC/VS 下输出结果却是 12 呢?期待您回复。 如果成员之间穿插着非位域成员,那么不会进行压缩。...例如对于下面的 bs: struct bs{ unsigned m: 12; unsigned ch; unsigned p: 4; }; 在各个编译器下 sizeof 结果都是

2.4K40

C语言内存地址基础

在输出中,我们看到地址是 16 进制。更值得注意是,字符地址前后相差1字节。int 型变量地址前后相差四字节。内存地址算法、指针算法、都是根据所引用类型大小。...一个给定类型大小是依赖于平台,我们这个例子中char 是1字节,int是四字节。将字符地址-1是改地址前地址,而将int型地址-1是该地址前4个地址。...在实际中,大多数编译器会 使结构体中每个成员与结构体最大成员有相同大小, 在我们例子中,你可以看到char实际上占用4字节,整个struct占用12个字节。都发生了什么?...1.struct变量指向struct首元素地址 2.不要去假设一个结构体成员相对于另外一个成员有多少内存偏移量,结构体成员之间可能有边界字节,或者编译器也可能将它们放在不连续内存空间中。...使用地址操作符&来获得成员地址 3.使用sizeof(struct instance)来获得struct大小,不能假设它是各个成员大小大小总和,也许还有填充字节。

2.5K80

【C】结构体+自定义类型知识点大全(基础,进阶,简洁,全面)

特点: 可以把结构体名字去掉 看似相同,编译器会把当作不同结构体类型 例: 2.访问结构体成员 有两种访问方式: 结构体变量 ....//详情见同一博客,“访问结构体成员” 自定义类型部分:(进阶部分) 一.自定义类型分类 自定义类型: 结构体(struct) 枚举(enum) 联合体(union) 二.结构体内存类型 计算结构体内存大小...结构体第一个成员直接对齐到相对于结构体变量起始位置为0偏移处 从第二个成员开始,要对齐到某个【对齐数】整数倍偏移处 结构体大小,必须是最大对齐数整数倍 例: 二:为什么存在结构体内存对齐...一般不混用,不确定储存方向,有可能截断/整型提升); 位段涉及很多不确定因素,位段是不跨平台,注重可移植程序应该避免使用位段; 场景引入:为什么使用位段后,A大小从16变为8?...5,不是最大对齐数4整数倍,因此对齐到4整数倍8 例2: PS:short默认对数为2 分析: 最大成员大小是12是最大对齐数4整数倍,故联合体大小为12

6910

ios 底层原理 : 类与类结构分析

,而结构体类型内存大小是由内存属性决定,(结构体指针才是8字节) bits属性:只有首地址经过前面3个属性内存大小总和平移,才能获取到bits 计算cache类内存大小 进入cache类,cache_t...别名,占 2个字节 #endif uint16_t _occupied; //是uint16_t类型,uint16_t是 unsigned short 别名,占 2个字节 计算前两个属性内存大小...,有以下两种情况,最后内存大小总和都是12 情况1:if流程 buckets是struct bucket_t *类型,是结构体指针类型,占8字节 mask是mask_t类型,而mask_t是unsigned...从打印结果可以看出,bits存储信息,类型是class_rw_t ,也是一个结构体类型,但是我们还没看到属性列表,方法列表等信息 探索属性列表,即property_list 通过查看class_rw_t...,method_list,protocols方法,还有一个ro方法,返回类型是class_ro_t,通过查看他定义,发现其中有一个ivar_list_t * ivars;属性,所以我们猜测,成员变量就存在于

58220
领券