位段、联合体、动态内存浅谈

位段

位段的声明和结构体是类似的,有两个不同:

1.位段的成员必须是int, unsigned int 或 signed int

2.位段的成员名后面有一个冒号和一个数字

比如int age:10; 就是给age十个比特位

struct S
{
	char a : 3;//5
	char b : 4;//1
  //开辟新字节
	char c : 5;//3
  //开辟新字节
	char d : 4;
};

int main()
{
	int a = 10;
	int b = 20;
	struct S s = { 0 };
	s.a = 10; //1010 只能存3bit 就是010存进去了
	s.b = 12; //1100 全部存入
	s.c = 3; //00011,因为c占5bit
	s.d = 4; //0100

	return 0;
}

位段仍然需要考虑对齐问题,比如上面的代码

假设默认对齐数为8,在S内char类型的对齐数为一个字节,也就是8bits

a和b加一起只占7bits,第一个字节只剩1 bit,由于要对齐1个字节(8 bits)所以对齐数必须是8的倍数,所以到了c时,必须要重新开辟一个字节给c,因为c占5bits

到了d时,如果把d放入和c同一个字节,就会溢出,因为9>8

所以,又需要给d开辟一个新字节,最后一共开辟了3个字节(24 bits,为8的倍数)

联合体

联合体,也被称为共用体,和结构体类似,但是所有不同类型的变量会存储在同一段内存单元中

来看下面一段代码

union Un
{
	char c;//1
	int i;//4
};

int main() 
{
	union Un u = {0};
	u.c = 'w';
	u.i = 0x11223344;
	printf("%d\n", sizeof(u));//4
    //联合体也叫共用体
	printf("%p\n", &u);//02E2F8A0
	printf("%p\n", &(u.c));//一样 - 02E2F8A0
	printf("%p\n", &(u.i));//一样 - 02E2F8A0

	return 0;
}

u的大小只有四个字节,这是因为c和i共享了同一段内存单元

如果打印u,u.c和u.i的地址的话,会发现它们的地址相同

联合体的对齐问题:

union Un1
{
	char c[5];//5 1,8 - 1 (char)对齐数
	int i;    //4 4,8 - 4 (int) 5不是4的倍数,所以浪费三个字节,8
};

由于所有变量都会存储在一起,所以只需要考虑最大对齐数即可

Un1里面的最大对齐数为4,因为i是int型

Un1本来只需要5个字节就可以存储,但是由于最大对齐数为4,5不是4的倍数

所以必须要对齐并浪费3个字节,最终Un1占8个字节

动态内存分配:

malloc

void *malloc( size_t size );

malloc的作用是在动态区分配一段长度为size的连续空间,它的返回值是其区域的起始地址

下面举例打印1-10

int main()
{
	//开辟10个整型的空间
	//int arr[10];
	int* p = (int*)malloc(40);
	if (NULL == p)
	{
		printf("%s\n", strerror(errno));//如果p为NULL,则返回错误指令
		return 0;
	}
	//使用
	int  i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	//释放
	free(p);//当释放后,p就是野指针了
	p = NULL;
	
	return 0;
}

首先给malloc强转成int*类型,然后在括号里添加需要的内存大小

需要注意的一点是,当时用完malloc后,必须要使用free()释放该指针,并让该指针指向NULL

free函数可以释放该动态内存分配的地址,使其变为野指针

calloc

void *calloc( size_t num, size_t size );

calloc的作用是在在动态区中分配num个长度为size的连续空间

int main()
{
	//开辟10个整型的空间
	//int arr[10];
	int* p = (int*)calloc(10, sizeof(int));
	if (NULL == p)
	{
		printf("%s\n", strerror(errno));//如果p为NULL,则返回错误指令
		return 0;
	}
	//使用
	int  i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	//释放
	free(p);//当释放后,p就是野指针了
	p = NULL;
	
	return 0;
}

用法跟malloc类似,不同的是当calloc分配完内存时,会自动将内存初始化为0

realloc

void *realloc( void *memblock, size_t size );

realloc函数用来重新分配内存空间

当malloc和calloc分配到内存空间不足时,可以用realloc调整

当memblock为NULL时,相当于malloc,即分配size字节的内存空间

int main()
{
	//开辟10个整型的空间
	//int arr[10];
	int* p = (int*)realloc(NULL, 40);
	if (NULL == p)
	{
		printf("%s\n", strerror(errno));
		return 0;
	}
	//使用
	int  i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	//释放
	free(p);
	p = NULL;

	return 0;
}

只有用 malloc()、calloc()、realloc() 分配成功的指针才能被 realloc() 函数接受

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值