C与指针——结构、联合、内存对齐、位域

发布于:2025-06-05 ⋅ 阅读:(25) ⋅ 点赞:(0)

1、定义结构与初始化

struct A
{
int d1;
int d2[3];
};
A a={1,{1,1,1}};

2、补充内容:内存对齐

struct A
{
	char c1;
	int d1;
	char c2;
};
struct B
{
	char c1;
	int d1;
	char c2;
	double d2;
};

一般情况下,int 长度是4字节,要求起始地址与4对齐。那么该结构体中对对齐要求最严格的数据结构就是int,所以会强制让该结构的起始地址满足4的倍数要求。
在内存中会先存储c1,然后空3个字节(满足了d1地址被4整除要求),然后存d1,再存c2。然后再保留3个字节的空白位置。这样内存开销为12(1+3+4+1+3)
对于B,对齐要求为double(8),因此开销为24(1+3空+4+1+7空+8)
我们可以通过调整struct中变量的顺序来节约内存空间。A调整为

struct A
{
int d1;
char c1;
char c2;
};

这样内存开销为8(4+1+1+2)。
3、补充内容:联合和结构在函数传参的时会被完全拷贝一份,传入的是副本
4、补充内容:struct可以用于实现位段——按位分配内存

struct A
{
unsigned int d1:1;
unsigned int d2:1;
unsigned int d3:19;
};

int main()
{
	A a;
	a.d1 = 0;
	a.d2 = 1;
	a.d3 = 122;
}

其中d1,d2,d3就被称之为位段。各占据1,1,19个位。
位段的数据类型最常见的是unsigned int,int, unsigned char三种。

补充

不管字节序还是比特序,大端模式是低地址存放高位数据,高地址存放低位数据。
大端模式的字节序:0x123456 ,内存地址从低到高存储的是56,34,12
大端模式的比特序:0x8 ,内存位从低到高存储的是0001 0000
网络序的字节,统一采用大端模式。

5、联合——同一内存空间存不同类型数据

union A
{
	int d1;
	float d2;
};//4个字节的空间,即存储了d1又存储了d2.成员的类型决定了位是如何被解释的。
union A a;
a.d2 = 3.1415;
printf("%d",a.d1);

联合的sizeof 由联合中的最大元素决定,

union A
{
	int d1;
	double d2;
};
union A a;
a.d2 = 3.1415;
printf("%d",sizeof(a));//输出是8.

6、补充内容——sizeof()的参数可以是变量也可以是类型

特殊使用场景———零长度数组

struct Msg
{
int l;
int s;
int v[0];
}

这个结构体实例化以后,sizeof()的结果是8,因为数组长度为0,不会占用任何内存。但是在使用的时候可以灵活的调整数组的长度。例如

struct Msg* msg = malloc(sizeof(struct Msg)+sizeof(int)*6);
for(int i=0;i<6;i++)msg->v[i]=i;//这里就是非常灵活的使用

当然实际上引入了VLA以后可以等价为

struct Msg
{
int l;
int s;
int k;
int v[k];
}

网站公告

今日签到

点亮在社区的每一天
去签到