首先来看一段代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<Windows.h>
struct Node
{
int date;
char next;
};
int main()
{
struct Node n;
printf("%d", sizeof(n));
system("pause");
return 0;
}
输出结果为8
以我们平时的了解,结构体占用内存字节应该是该结构体成员占用内存字节的和,在这段代码中输出结果应该是5。但是为什么会输出8呢?
这就牵扯到一个知识点 结构体内存对齐
想要看清楚刚才为什么会出现8,我们来用一个宏“offsetof”
这个宏实现的是一个结构成员相对于结构开头的字节偏移量
下面是 offsetof() 宏的声明。
offsetof(type, member-designator)
C 标准库 - <stddef.h>
用这个库宏可以实现对结构体字节偏移量的观察。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<Windows.h>
#include<stddef.h>
struct Node
{
int date;
char next;
};
int main()
{
struct Node n;
printf("%d\n", sizeof(n));
printf("%d\n", offsetof(struct Node, date));
printf("%d\n", offsetof(struct Node, next));
system("pause");
return 0;
}
结果是 8
0
4
可以看到Int类型的成员并没有偏移,但是char类型的成员偏移量为4,所以造成了这个结构体的长度为8
结构体为什么要内存对齐呢?
1:一些硬件规定数据必须在特定位置开始取;
2:处理器在访问未对齐的内存需要进行2次访问,而对齐的内存只需要进行一次访问就行。
结构体内存对齐的规则是什么?
1:结构体的第一个成员都要放在起始位置的0偏移处;
2:从第二个成员开始,每个成员都要放在某个对齐数的整数倍的偏移处;
这个对齐数:成员自身大小和默认对齐数的较小值
默认对齐数:
VS:8
linuix : 4.
3:结构体的总大小必须是所有成员的对齐数中最大对齐数的整数倍。
我们继续看一个结构体嵌套类型的计算
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<Windows.h>
#include<stddef.h>
struct Diss
{
double num;// 0偏移量 0--7
char name;// 8偏移量 8
int age;// 4偏移量 12--15
}d;// 8+4+4 最后结果取最大对齐数的整数倍所以是16
struct Node
{
int date;//0偏移量 0--3
char next;//4偏移量 4
struct Diss n;//由于5不是24的倍数,结构体会偏移到8开始 8----24
}p;//4+4+16 这里最大对齐数为8而不是16,因为默认对齐数和自身长度比较选的是较小值,所以在此事的最大对齐数是8
int main()
{
struct Node n;
printf("%d\n", sizeof(d));
printf("%d\n", offsetof(struct Node,date));
printf("%d\n", offsetof(struct Node, next));
printf("%d\n", offsetof(struct Node, n));
printf("%d\n", sizeof(p));
system("pause");
return 0;
}
16
0
4
8
24
结果是不是如你所愿呢?