结构体的内存分配
1.1内存对齐(解决结构体的大小)
1.结构体第一个成员对齐到起始偏移量为0的地址处.
2.其他成员要对齐到某个数字(对齐数)的整数倍的地址处.
对齐数=编译器默认的一个对齐数与该成员变量大小的较小值
—vs默认的对齐数是8
—linux中没有默认对齐数,对其数是成员自身的大小
3.结构体的大小是最大对齐的整数倍.
4.结构体中嵌套结构体时,该结构体的对齐到它内部成员最大对齐数的整数倍
eg:
struct s
{
char c1;
int a1;
char c2;
};//所占内存大小是12字节
struct s1
{
char c1;
struct s s3;
double d;
};//所占内存大小是24字节
核心:对齐数是多少和从哪开始对齐.
1.2上述规则的原因:
1.不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.一次性拿出想要的数据,假如每次处理器读取四个字节,int类型的数据对齐的位置正好是四的倍数,所以每次都可以读取到int类型的数据,如果没有采取对齐,需要两次读取才可以读到数据,通过牺牲空间才提升效率.
注意:
在设计结构体的时候可以将占用空间小的变量集中在一起, 可以节省空间
1.3修改默认对其数
#pragma修改默认对齐数
#pragma pack(1) //设置默认对齐数为1
#pragma pack() //取消设计的默认对齐数恢复到系统的默认对齐数
一般自己设置默认对齐数取2的n次方.
1.4结构体传参
struct s
{
int data[100];
int num;
};
void print1(struct s t)//传递结构体变量——传值调用
{
for(int i=0;i<3;i++)
{
printf("%d",t.data[i]);
}
}
void print2(struct s* ps)//传递结构体变量的地址——传址调用
{
for(int i=0;i<3;i++)
{
printf("%d",ps->data[i]);
}
}
int main()
{
struct s a1={{1,2,3},4};
print1(a1);
print2(&a1);
return 0;
}
用print2更好,减少时间和空间上的开销.
本文详细解释了结构体内存对齐的原理,包括对齐数的选择、原因以及如何通过`#pragmapack`修改默认对齐。还讨论了结构体传参时的传值与传址调用,强调了传址调用在时间和空间效率上的优势。
6389





