哪个网站可下载免费ppt,深圳vi设计内容,品牌形象设计包括哪些内容,安装vs2015网站开发000、前言
要想计算结构体内存大小#xff0c;就会涉及到一个结构体内存对齐的问题#xff0c;而不是对其成员进行简单的加运算
#xff08;1#xff09;在写本博客之前
有位同学和我讨论了一个学校的题目#xff0c;题目如下#xff1a; 我借这道题目问了另外一位同…000、前言
要想计算结构体内存大小就会涉及到一个结构体内存对齐的问题而不是对其成员进行简单的加运算
1在写本博客之前
有位同学和我讨论了一个学校的题目题目如下 我借这道题目问了另外一位同学这位同学认为答案为12理由是这样的 “4int的大小4y数组的大小4float的大小12” 2我的思考
老实说我不太好评价学校的C语言课但是这道题目如果没有细讲的话很有可能造成一定程度上的误解。稍微知道结构体内存对齐的老铁就会明白这个结构体的大小的确是12但是绝不是简单意义上的大小言外之意这道题是个大坑
3我的代码提问
我当时写了一个文档发给了这位同学
int main()
{struct a{int x;char y[4];float z;};//一种朴素的想法当然是444啦但是肯定不对……//不信你看这个程序printf(%zd\n, sizeof(struct a));//输出的也是12啊怎么不对了是的不对这个只是巧合因为成员刚好大小都是4个字节这与放了三个int成员是没有太大区别//但是如果是不同的就涉及到结构体内存对齐的问题了//假设我们将结构体内部成员换一下存在一个char类型的成员struct b{char i;int x;char y[4];float z;};//按照直接加的逻辑就是144413printf(%zd\n, sizeof(struct b));//你会发现结果是16//如果可以系统了解一下结构体对齐的知识吧需要的话我可以发个链接给你//但是这道题由于成员设置的比较简单因为结构体成员的类型都是4个字节直接简单相加得到的结果确实是对的都是这样的理解方式是有问题的return 0;
}001、结构体内存对齐规则
1规则一第一个成员变量在结构体变量偏移量为0的地址处
2规则二其他成员变量要对齐到“对齐数”的整数倍的地址处每个成员拥有一个对齐数对齐数“编译器默认的一个对齐数VS默认这个数是8”与“该成员大小”的较小值
3规则三结构体的总大小为最大对齐数每个成员对齐数最大的整数倍处
4规则四如果嵌套了结构体先计算这个被内嵌的结构体大小然后将这个被内嵌的结构体整体当成一个新类型就行
002、为什么存在内存对齐
1性能原因
数据结构应该尽可能的在自然边界上对齐。如果处理器访问了没有对齐的内存可能需要多次访问内存空间才能得到一个完整的数据
2平台原因
不是所有平台都可以访问任意地址上的数据的某些硬件平台只能在某些地址取出某些特定类型的数据否则抛出硬件异常
3实质原因
牺牲空间换时间的做法
003、结构体大小推导例子
1例子一
struct S1
{char c1;//char大小为1和默认对齐数8比该成员的成员对齐数是1char c2;//char大小为1和默认对齐数8比该成员的成员对齐数是1int i;//整型大小为4和默认对齐数8比该成员的成员对齐数是4
};//最大成员对齐数是4结构体总大小必须是4的倍数
printf(%d\n, sizeof(struct S1));//结果为82例子二
struct S2
{char c1;//大小为1和默认对齐数比该成员的成员对齐数是1int i;//大小为4和默认对齐数比该成员的成员对齐数是4char c2;//大小为1和默认对齐数比该成员的成员对齐数为1
};//最大成员对齐数是4结构体的总大小必须是4的倍数
printf(%d\n, sizeof(struct S2));//结果为12注意不是9因为要满足规则三3例子三
//嵌套结构体
struct S3
{double d;//大小为8和默认对齐数8相比该成员的成员对齐数为8char c;//大小为1与默认对齐数8相比该成员的成员对齐数为1int i;//大小为4与默认对齐数8相比该成员的成员对齐数为4
};//最大成员对齐数为8结构体的总大小必须是8的倍数
printf(%d\n, sizeof(struct S3));//输出16struct S4
{char c1;//大小为1与默认对齐数8相比该成员的成员对齐数为1struct S3 s3;//大小为16与默认对齐数8相比该成员的成员对齐数为8double d;//大小为8与默认对齐数8相比该成员的成员对齐数为8
};//最大成员对齐数为8结构体的总大小必须是8的倍数
printf(%d\n, sizeof(struct S4));//值为32S3的大小 S4的大小
004、在VS2022中如何修改默认对齐数
1使用#pragma
利用#pragma这个预处理指令就可以改变默认对齐数
2具体代码
使用#pragma的具体代码这里的代码可以自己尝试画图解决
①代码一
#include stdio.h
#pragma pack(8)//把默认对齐数设置为8
struct S1
{char c1;//char大小为1和设置后的默认对齐数8比该成员的成员对齐数是1char c2;//char大小为1和设置后的默认对齐数8比该成员的成员对齐数是1int i;//整型大小为4和设置后的默认对齐数8比该成员的成员对齐数是4
};//最大成员对齐数是4结构体大小必须是4的倍数
#pragma pack()//取消设置的默认对齐数还原为默认值int main()
{printf(%d\n, sizeof(struct S1));//结果为8
}②代码二
#pragma pack(1)//设置默认对齐数为1
struct S2
{char c1;//大小为1和设置后的默认对齐数1比该成员的成员对齐数是1int i;//大小为4和设置后的默认对齐数1比该成员的成员对齐数是1char c2;//大小为1和设置后的默认对齐数1比该成员的成员对齐数为1
};//最大成员对齐数是1结构体大小必须是1的倍数
#pragma pack()//取消设置的默认对齐数还原为默认int main()
{printf(%d\n, sizeof(struct S2));//结果为6return 0;
}这里注意当默认对齐数为1的时候此时对结构体成员进行简单加法运算得到结构体大小是没有问题的 005、注意
如果你认真看完了上面的内容你就会发现这里面最重要的就是对齐数的确认而编译器自身携带的默认对齐数更是会直接影响结构体的的大小。
然而现实是不同的编译器的默认对齐数有可能是不一样的甚至有的编译器直接就没有这方面的规定例如下面这一串代码
#include stdio.h
int main()
{//嵌套结构体struct S3{double d;char c;long double i;};printf(%d\n, sizeof(struct S3));struct S4{char c1;struct S3 s3;double d;};printf(%d\n, sizeof(struct S4));return 0;
}1VS环境下 2在vscode使用mingw64的gcc工具环境下 据听说本题还被作为考试题目当作检验C语言课程学习来使用如果讲了也就罢了若是没讲就算考生得到12这个结果指开头的题目真的不会影响他对结构体内存的理解么私认为本题目不够严谨……