当前位置:网站首页>对C语言结构体内存对齐的理解
对C语言结构体内存对齐的理解
2022-08-01 21:02:00 【panfei263031】
参考文章:
C语言问题集——结构体及其内存对齐
Linux字节对齐的那些事
linux中,默认情况下,没有默认的对齐数,结构体中各个成员的类型占内存大小就是该成员的对齐数,所以对于结构体内存对齐,有如下规则:
1、第一个成员存放在内存偏移为0的地址处;
2、结构体中各个成员的类型占内存大小就是该成员的对齐数,各成员存放的起始地址应该是对齐数的整数倍;
3、整个结构体大小应该是该结构体中最大成员的对齐数的整数倍。
引用一下第二个参考连接中的话,就是:
二、对齐规则
对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐: 数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。 联合 :按其包含的长度最大的数据类型对齐。 结构体: 结构体中每个数据类型都要对齐。
但是也可以通过#pragma pack (n)伪指令设置默认对齐数,例如设置为4字节对齐,通过伪指令#pragma pack ()取消默认对齐数设置。
如果设置了默认的对齐数,对齐规则稍有变化,引用上述第二个参考连接中的描述:
#pragma pack(n) 用来设定变量以n字节对齐方式。 n字节对齐就是说变量存放的起始地址的偏移量有两种情况:
1、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式
2、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
结构的总大小也有一个约束条件,如果n大于等于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须是n的倍数。
接下来我们用同一个结构体,在没有设置默认对齐数和设置了4字节对齐两种情况下,分别测试该结构体的内存占用情况。
没有设置默认对齐数
测试代码:
#include<stdio.h>
#define offset(type, mb) (size_t)&(((type *)0)->mb)
#define print_offset(type, mb) printf("sizeof %s: %lu, index of %s: %lu\n", #type, sizeof(type), #mb, offset(type, mb))
typedef struct test_st
{
char a;
double b;
short c;
int d;
double e;
char f;
char g;
char h;
}test_st;
void main(void)
{
print_offset(test_st, a);
print_offset(test_st, b);
print_offset(test_st, c);
print_offset(test_st, d);
print_offset(test_st, e);
print_offset(test_st, f);
print_offset(test_st, g);
print_offset(test_st, h);
}
运行结果如下:
[email protected]:~/111# ./a.out
sizeof test_st_st: 40, index of a: 0
sizeof test_st_st: 40, index of b: 8
sizeof test_st_st: 40, index of c: 16
sizeof test_st_st: 40, index of d: 20
sizeof test_st_st: 40, index of e: 24
sizeof test_st_st: 40, index of f: 32
sizeof test_st_st: 40, index of g: 33
sizeof test_st_st: 40, index of h: 34
内存对齐的情况描述如下:
根据上述分析,上述结构体占40字节的内存。
设置4字节对齐
代码和上述差不多,就是在结构体定义的前后增加#pragma pack(4)和#pragma pack()的设置,运行结果如下:
[email protected]:~/111# ./a.out
sizeof test_st: 32, index of a: 0
sizeof test_st: 32, index of b: 4
sizeof test_st: 32, index of c: 12
sizeof test_st: 32, index of d: 16
sizeof test_st: 32, index of e: 20
sizeof test_st: 32, index of f: 28
sizeof test_st: 32, index of g: 29
sizeof test_st: 32, index of h: 30
从这两个实验的结果来看,确实符合上述对齐规则。
边栏推荐
- 98.嵌入式控制器EC实战 EC开发板开发完成
- Telnet弱口令渗透测试
- MySQL 中出现的字符编码错误 Incorrect string value: ‘\x\x\x\x‘ for column ‘x‘
- 记录第一次给开源项目提 PR
- Remove 360's detection and modification of the default browser
- 虚拟机的IP地址自动变为127.0.0.1
- 关于Request复用的那点破事儿。研究明白了,给你汇报一下。
- 【Kaggle】House Prices
- 网络安全与基础设施安全局(CISA):两国将在网络安全方面扩大合作
- Buttons with good user experience should not have hover state on mobile phones
猜你喜欢
98.嵌入式控制器EC实战 EC开发板开发完成
【Dart】dart构造函数学习记录(含dart单例模式写法)
【接口测试】JMeter调用JS文件实现RSA加密
What is the difference between a utility model patent and an invention patent?Understand in seconds!
面试突击70:什么是粘包和半包?怎么解决?
JS提升:手写发布订阅者模式(小白篇)
R语言 pca主成分分析的主要方法
Buttons with good user experience should not have hover state on mobile phones
人工智能可信安全与评测
用户身份标识与账号体系实践
随机推荐
Nacos 配置中心
Godaddy domain name resolution is slow and how to use DNSPod resolution to solve it
技能大赛训练:A部分加固题目
C专家编程 第1章 C:穿越时空的迷雾 1.3 标准I/O库和C预处理器
string
织梦发布文章提示body has not allow words错误
系统收集集
98.嵌入式控制器EC实战 EC开发板开发完成
任务调度线程池-应用定时任务
PyTorch笔记 - Attention Is All You Need (2)
技术栈概览
列表页常见的 hook 封装
【Dart】dart构造函数学习记录(含dart单例模式写法)
微服务负载均衡器Ribbon
面试官:大量请求 Redis 不存在的数据,从而打倒数据库,有什么方案?
Protocol Buffer 使用
idea实用快捷键合集——持续更新
Custom command to get focus
What is the difference between a utility model patent and an invention patent?Understand in seconds!
Pytorch框架学习记录10——线性层