文章目录
前言
提示:仅供参考
一、结构体内存对齐
1.什么是结构体内存对齐?
编译器在计算结构体大小时,发生内存对齐
如:
struct s{
char c;
int i;
};
int main(){
printf("%d\n",sizeof(struct s));
return 0;
}
问:程序的结果是多少?
char 一个字节;int 4个字节
1+4=5 ?
答案是 8。
2.内存对齐的规则:
a. 第一个成员偏移量为0。
b. 其他成员要在(偏移)对齐数的整数倍。
对齐数:编译器默认对齐数与成员变量大小中的较小值
c. 结构体的总大小是成员中最大对齐数的整数倍。
d. 若有结构体嵌套,内结构体对齐自己的最大对齐数整数倍偏移量,外结构体整体大小是所有最大对齐数的整数倍(含内结构体成员的对齐数)
举例说明更形象化:如
struct s{
char c; /大小为1, 默认对齐数为8,取1作为对齐数
int i; /大小为4 ,默认对其数为8,取4作为对齐数,在4的倍数偏移处开始存储
};
int main(){
printf("%d\n",sizeof(struct s));
return 0;
}
第一个成员char 与结构体的偏移量为0,即占据了第一个字节。
第二个成员int 大小是4字节,vs平台下默认对齐数是8 ,取较小值 4 作为此成员的对齐数,->即变量 i 要在偏移为4的整数倍地址处开始存储 往后存4个字节:内存图:
3.为什么存在结构体内存对齐?
α. 平台原因:并非所有硬件平台都能访问任意地址上的任意数据;某些硬件平台只能在特定地址上取值特定类型的数据。
β. 性能原因:数据结构应该尽可能在自然边界上对齐,原因在于,访问未对齐内存时,某些数据需要处理器访问两次才能得到完整数据,而对齐的内存仅需一次。
内存对齐 - -> 空间换时间。
4.vs平台下如何修改默认对齐数?
a. 预编译命令:#pragma pack(num)
修改编译器默认对齐数为num个字节
b. pack不带参数,则恢复平台默认对齐数
#pragma pack(4) /将默认对齐数修改为4字节
#pragma pack() /恢复默认对齐数为平台默认对齐数
二、位段
1.什么是位段?
位段的声明与结构体类似
语法为:
struct A{
int a:2;
int b:5;
}
2.位段的实现:
α. 位段成员必须是int、unsigned int、char。
β. 位段成员后有一个冒号和一个数字。数字表示分配几个bit位
3.位段存在的意义
在一定程度上节省空间
4.vs平台下位段中内存的使用形式
a. 在空间上以4字节(int)或1字节(char)方式来开辟。
b. 前一个空间剩余的bit位不够时,直接浪费,使用新开辟空间的bit位。
c. 一个字节内部从低位向高位使用。
5.位段存在的问题:
C语言标准并未规定上一个空间没用的bit位能否下一个空间继续使用;因此各个编译器都有自己的实现。
位段最大的问题是跨平台的问题:
a. int位段不确定有无符号。
b. 位段中最大位数不确定.
c. 位段的成员在内存中分配方式不确定.
d. 当一个结构含两个位段,第二个位段大于第一个位段余留的空间时,余留空间是舍是用不确定。
总结:
在编写程序时,考虑到结构体存在内存对齐,可以将结构体中的成员变量合理安排位置,使程序所需内存空间得到有效利用。