一.结构体内存对齐规则:
1.第一个成员在结构体变量偏移值为0的位置
2.其他成员,其自身字节大小与编译器中默认对齐数相比,取相比较中的小的值为其所为其成员开辟的内存空间的大小。(没有默认对齐数时,自身大小就是自己的对齐数)
3.编译器中默认对齐数:VS是8,Linux环境下没有默认对齐数。
4.最终结构体总大小为结构体成员中最大对齐数的整数倍。
为什么存在内存对齐:
1.不是所有的硬件平台都能访问任意位置的任意数据。某些只能访问特定类型的数据,否则会导致硬件错误。
2.数据结构(尤其是栈)应尽可能在自然边界上对齐。
总结:
结构体内存对齐,其实质是拿空间换时间效率,所以在设计结构体时,应该让占用内存空间小的成员集中在一起。
补充:
offsetoff ----宏,计算结构体成员相对于起始位置的偏移量。
运用:需添加头文件#include <stddef.h>,offsetoff(structName,numberName)
3.修改默认对齐数
在VS中默认对齐数为8,但其实是可以修改编译器的默认对齐数
在头上 ---->> #pragma pack(n),n为修改的对齐数,此时在该程序中的(是该程序!!!)中的默认对齐数是n,所以此时在结构体中计算结构体大小的时候按修改的默认对齐数来计算。
但默认对齐数为1的时候,其实是按不对齐的方式来计算,但也不要随意乱改,一般都是参照2的n次方来设置,得考虑整个硬件的兼容,别太任性了。
二.结构体传参
struct S s={ int a[4], int num };
struct S s={{1,2,3,4},1000};
void print1(struct S s) //结构体传参--传结构体
{
printf("%d\n",s.num);
}
void print2(struct S* ps) //结构体地址传参---传地址
{
printf("%d\n",ps->num);
}
结构体传参的时候,尽量传结构体的地址,因为函数传参时,参数是需要压栈,对时间空间有开销,结构体过大的时候,开销就比较大,效率变低,所以传地址即可以方便改值,也可以提高性能效率。
三.枚举
枚举简单来说就是把可能的取值一一列举出来,比如一年有12个月,就可以来一一列举
定义:
enum Sex
{ MALE, //0
FEMALE, //1
SECRET //2
};
int main()
{ enum Sex s=MALE;
enum Sex s2=FEMALE;
printf("%d\n",MALE); //0
printf("%d\n",FEMALE); //1
printf("%d\n",SECRET); //2
}
若在枚举中将MALE=5,会从上一个数字依次接下。
注意:改变枚举变量中的初值只能从枚举中改变。
枚举的优点:
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较枚举有类型检查