当前位置:网站首页>C语言结构体字节对齐问题
C语言结构体字节对齐问题
2022-06-23 10:20:00 【stone_322】
1 前言
对于结构体字节对齐问题,我发现我一直有一个误区,正是这个误区,给我带来了很大困扰,今天突然顿悟,在此记录一下,希望能帮到大家。
2 举例
#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)0)->f))
struct AD {
int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1 {
int a; char b[13]; double c;};
#pragma pack(2)
struct A2 {
int a; char b[13]; double c;};
#pragma pack(4)
struct A4 {
int a; char b[13]; double c;};
#pragma pack(8)
struct A8 {
int a; char b[13]; double c;};
#pragma pack(16)
struct A16 {
int a; char b[13]; double c;};
#pragma pack(pop)
int main()
{
printf("AD.a %d\n",field_offset(AD,a));//AD.a 0
printf("AD.b %d\n",field_offset(AD,b));//AD.b 4
printf("AD.c %d\n",field_offset(AD,c));//AD.c 24
printf("AD sizeof %d\n", sizeof(AD));//AD sizeof 32
printf("\n");
printf("A1.a %d\n",field_offset(A1,a));//A1.a 0
printf("A1.b %d\n",field_offset(A1,b));//A1.b 4
printf("A1.c %d\n",field_offset(A1,c));//A1.c 17
printf("A1 sizeof %d\n", sizeof(A1));//A1 sizeof 25
printf("\n");
printf("A2.a %d\n",field_offset(A2,a));//A2.a 0
printf("A2.b %d\n",field_offset(A2,b));//A2.b 4
printf("A2.c %d\n",field_offset(A2,c));//A2.c 18
printf("A2 sizeof %d\n", sizeof(A2));//A2 sizeof 26
printf("\n");
printf("A4.a %d\n",field_offset(A4,a));//A4.a 0
printf("A4.b %d\n",field_offset(A4,b));//A4.b 4
printf("A4.c %d\n",field_offset(A4,c));//A4.c 20
printf("A4 sizeof %d\n", sizeof(A4));//A4 sizeof 28
printf("\n");
printf("A8.a %d\n",field_offset(A8,a));//A8.a 0
printf("A8.b %d\n",field_offset(A8,b));//A8.b 4
printf("A8.c %d\n",field_offset(A8,c));//A8.c 24
printf("A8 sizeof %d\n", sizeof(A8));//A8 sizeof 32
printf("\n");
printf("A16.a %d\n",field_offset(A16,a));//A16.a 0
printf("A16.b %d\n",field_offset(A16,b));//A16.b 4
printf("A16.c %d\n",field_offset(A16,c));//A16.c 24
printf("A16 sizeof %d\n", sizeof(A16));//A16 sizeof 32
printf("\n");
return 0;
}
如果你认为的结果和上面注释中的一样,那你就没有必要读下去了。
在上面的例子中,对于A1,A2, A4的结果我都理解,但是对AD,A8,A16我很不理解。
对于AD,我认为结果应该是:
AD.a 0
AD.b 8
AD.c 24
AD sizeof 32
我是这样想的:AD应该是8字节对齐的,a是4字节,b占13字节,a后面虽然空了4个字节,但是放不下b,所以应该是a后面补4个字节,接着放b。b13个字节,不是8的倍数,所以b后面补3个字节。接着c占8个字节。
当然,我上面的想法是错误的。可是为什么会错呢?
其实,问题出在b的身上。b是一个char型的数组,即类型为char *,但是我们访问的是b的元素,即char,所以,b的自身对齐值为1,而不是13。
之所以这里出错,实际上是因为没有深刻认识到为什么要字节对齐。字节对齐是为了提高CPU访问数据的效率。32位字长的计算机,其CPU一次可以读写的数据长度是4个字节64位计算机则一次可以读取8个字节。对于char型数组,只占据一个字节,小于计算机一次读取的字节数,所以无论其元素放在什么地址,都可以一次读取到,便“不需要”字节对齐。所以,b的元素是可以紧挨着a来放的,所以AD实际空间存放情况应如下图所示:

AD成员中自身对齐值最大的为8, 所以AD的自身对齐值是8;A8的指定对齐值和自身对齐值一样,相当于没指定,还是8字节对齐;A16指定对齐值16大于自身对齐值8,所以还是8字节对齐。所以AD,A8,A16的结果是一样的。
3.其他
这是一个C++程序:
#define field_offset(s,f) (int)(&(((struct s *)0)->f))
int main() {
struct alignas(4) Info {
char a;
short b;
char c;
};
std::cout << sizeof(Info) << std::endl;
std::cout << field_offset(Info, a) << std::endl;
std::cout << field_offset(Info, b) << std::endl;
std::cout << field_offset(Info, c) << std::endl;
return 0;
}
刚开始我以为应该是下面这样的:
所以sizeof(Info) = 4。
但运行结果为:
8
0
2
4
可以推断出,Info的实际存储情况应该为:
针对此,我有2个问题:
- C++11标准中,alignas不是最小设置8字节对齐,也就最小是alignas(8),否则设置无效吗?为什么还会出现上面的结果呢?
- 如果
alignas(4)设置生效,根据第二节的例子中提到的:结构体的有效对齐值是自身对齐值和指定对齐值中较小者。那么实际存储情况像下面这样(sizeof(Info)= 6)啊:
是因为C和C++标准不一样吗?
后续:经过验证,我得到了答案。
参考链接:
边栏推荐
- R and rstudio download and install detailed steps
- 详解判断大小端的方法
- Solve the problem that Preview PDF cannot be downloaded
- 开源二进制文件静态漏洞分析工具BinAbsInspector安装使用
- 社招腾讯高P(高级产品经理)的面试手册
- What is a good quick development framework like?
- Golang 快速上手 (1)
- Implementing Domain Driven Design - using ABP framework - General guidelines
- 图片存储--引用
- 春招面试经验汇总(技术岗)
猜你喜欢

R and rstudio download and install detailed steps

马斯克 18 岁儿子请愿改名,欲断绝父子关系

Unity技术手册 - 生命周期LifetimebyEmitterSpeed-周期内颜色ColorOverLifetime-速度颜色ColorBySpeed

Lying trough, the most amazing paper artifact!

RT thread add MSH command

Stockage d'images - référence

用贪吃蛇小游戏表白(附源码)

搭建一个点歌QQ机器人,另外还能看美女

当 Pandas 遇见 SQL,一个强大的工具库诞生了

文件IO(1)
随机推荐
2021-05-12内部类
Analysis of LinkedList source code
NFS挂载时一直没有同步文件
NOI OJ 1.3 04:带余除法 C语言
MySQL基础-笔记
Nuxt. Differences between JS spa and SSR
How does thymeleaf get the value of the request parameter in the URL?
Lying trough, the most amazing paper artifact!
Liujinhai, architect of zhongang Mining: lithium battery opens up a Xintiandi for fluorine chemical industry
炫酷相册代码,祝对象生日快乐!
Several practical software sharing
Noi OJ 1.2 integer data type storage space size
Noi OJ 1.3 04: C language with remainder Division
六张图详解LinkedList 源码解析
Unity technical manual - shape sub module - Sprite, spriterenderer and velocity over lifetime
R和RStudio下载安装详细步骤
构建信创产业生态,移动云立足全栈自主创新连放大招
天龙八部TLBB系列 - 网单服务端各目录文件说明【超详细】
详解判断大小端的方法
个人博客系统毕业设计开题报告