一.结构体
1.判断默认对其数对齐数,此概念在linux环境下没有,Linux环境下没有默认对齐数,对齐数就是变量本身大小,而在VS环境下,对齐数是默认对齐数(VS默认是8)和变量类型本身大小(若是数组,则其本身对齐数按每个元素的大小算,若是结构体则按照其体内最大的对齐数算他的对齐数)的最小值。(这里插一句#prampack()宏可以设定默认对齐数)
2.确定出结构体中每个变量的对齐数,第一个变量存储的地址是偏移量为零的地址处,其他变量存储的地址是偏移量为变量本身对齐数整数倍的地方,会有部分浪费空间。
3.最后判断如上计算出来的结构体大小是不是结构体中所有变量中最大对齐数的整数倍,若不是则需要将需要的储存空间变为最大对齐数的整数倍。(结构体大小必须是结构体中所有变量中最大对齐数的整数倍)。
例子:
typedef struct{
int a;
char b;
short c;
short d;
}AA_t;
二.位段
定义和结构体类似但内部变量只能是整形(int ,unsigned int ,unsigned char,char 等等 )
例子
struct Un1
{
int x : 2;
int y : 4;
};
struct Un
{
char x : 2;
char y : 4;
};
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(struct Un1));
printf("%d", sizeof(struct Un));
return 0;
输出 :4字节 和 1字节。
每次为不够用的变量开辟空间都开辟变量类型个空间 ,使用时每个字节从右向左使用,整体字节从低地址都高地址使用。(至于第一次分配剩下时,且第二个变量大于剩余部分大小,则第二个变量是用完这个,再去用新分配的还是直接用新分配的,这个不同的编译器实现不同,C没有明确规定怎么办,故位段存在不少跨平台问题)
分号后面的数字作用是为此变量分配几个bit位。
三.共用体(联合体)
特点:共用体内部变量共享一块地址,共享所占地址最大的变量的地址,都是从首地址处开始共享
修改一个变量两个变量都会被改变。
占用内存计算同样保证共用体的大小也需要是共用体中所有变量中最大对齐数的整数倍。
union Un
{
int arr[3];
double s;
};
#include<stdio.h>
int main()
{
printf("%d", sizeof(union Un));
return 0;
}
答案:16字节(不是12字节)。(占用内存计算同样保证共用体的大小也需要是共用体中所有变量中最大对齐数的整数倍。)