结构体(二)

结构体(二),第1张

目录
  • 位端
    • 什么是位端
    • 位端的内存分配问题
    • 位端的跨平台问题
    • 总结
  • 枚举
    • 枚举的定义
    • 枚举的优势
    • 枚举的使用
  • 联合体(共用体)
    • 联合体的定义
    • 联合体的特点
      • 试题引导
    • 联合体大小的计算
  • 链接


位端 什么是位端

位端跟结构体相似,但有两个不同;

位端的成员变量必须是 int , unsigned int , signed int
位端的成员后面有一个冒号数字
例如

//位端的演示
struct s
{
	int a : 2;
	int b : 2;
	int c : 2;
	int d : 4;
};

在这里 s 就是一个位端。

位端的内存分配问题
  1. 位端的结构体成员必须是 int , unsigned int , signed int ,或者是 char (整形家族)类型;
  2. 位端的空间开辟是按照 int 四个字节,char 一个字节
  3. 关于位端有许多不确定的因素(标准被定义),是不支持跨平台的,可移植的程序要避免使用位端。
    例题
struct s
{
	char a : 2;
	char b : 2;
	char c : 8;
	
}s;

int main()
{
	s.a = 1;
	s.b = 4;
	s.c = 6;
	printf("%d\n", sizeof(s));
	return 0;
}

结果演示

题目解析

这里我们看到结构体成员后面的数字代表 所占的bety位数
a 为 char 类型先开辟一个空间以供使用,a 占两个比特位,放入数字01,我们假设从高地址处想低地址处存放(每个平台设置的都不一样),剩下6个比特位;
b 占2个比特位,还有六个可以继续使用, b=100但是只能放两个比特位,舍去最高位放入00,还剩4个比特位;
c 占8个比特位,剩余的四个不够,再次开辟一个空间,剩下的四个空间可能使用可能不使用(C语言标准并未定义),c=0110,放入0110,不够进行补位;
2个字节

位端的跨平台问题
  • int 在位端中被当作有符号数,还是无符号数都是不确定的;
  • 位端中最大位的数目也是不确定的。(16位机器是16,64位机器是64,在16位机器中写成17会出问题)
  • 位端中的成员是从左往后分配,还是从右往左分配是不确定的。
  • 当结构体包含两个位端时,第二个位端所需要的空间大于所剩的空间时,
    会开辟新的空间,但是所剩的空间是否使用不确定。
总结

位端相较于结构体,会节省更多的空间,但是效率会下降。而结构体为了高效,会进行结构体对齐而浪费部分空间。


枚举

把可能的取值一一列举出来叫做列举。
列举的全程:enumeration
如:
星期: 星期一、星期二、星期三、星期四、星期五、星期六、星期日;
性别:男性、女性、保密;
月份: 一月、二月、三月、四月…十二月;

枚举的定义
enum day
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

enum sex
{
	male,
	female,
	secret
};

这里 enum day、enum sex都是枚举类型。
括号内的值叫做枚举常量。
我们发现枚举常量都是用逗号分隔开来,同时在定义完枚举类型后我们需要用分号来结束。

每个枚举常量都是有值的,默认都是从 0 开始,依次加一。

我们也可以修改这些值,只需要加上等号即可。
我们也可以只修改开头的值,设为5,它将从5开始,依次加一。

枚举的优势
  • 增加代码的可读性和可维护性;
  • 和 define 定义的标识性常量相比枚举有类型检查,更加严禁;
  • 防止命名污染;
  • 便于调试;
    使用方便一次可定义多个常量。
枚举的使用
//枚举的使用
enum menu 
{
	exit,
	start,
	suspend,
	end
};

int main()
{
	int input;
	scanf("%d", &input);
	switch (input)
	{
	case exit:
		break;
	case start:
		break;
	case suspend:
		break;
	case end:
		break;
	default:
		break;
	}
	return 0;
}

这样我在书写某些程序时,就不需要 case 0、case 1…再面对这样晦涩难懂的语句了。同时我们通过一个枚举,同时定义了好多值(如 exit = 0),不用再一一定义了。


联合体(共用体)

联合体是一种特殊的自定义类型,联合体的变量也包括各种类型,但是他们公用同一块空间,一个值改变另一个指也会跟着改变。

联合体的定义
//联合体的定义
union s
{
	char a;
	int b;
};

在这里我们定义了联合体。

联合体的特点 试题引导
//联合体的特点
union s
{
	char a;
	int b;
}s;
int main()
{
	s.a = 1;
	printf("%d\n", s.a);
	s.b = 2;
	printf("%d\n", s.a);
	printf("%p\n", &s.a);
	printf("%p\n", &s.b);
	return 0;
}

结果展示

我们发现当 b 改变时, a 也会跟着改变,我们还发现 a 和 b 的起始地址都是一样的。由此我们得出结论:联合体变量共用同一空间,一个值改变,另一个值也会受到影响。

联合体大小的计算
  • 联合体的大小为最大成员的大小;
  • 当最大成员不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍处。

试题演示

//联合体的大小
union s
{
	char a[19];
	int b;
}s;

union j
{
	int a[20];
	char b;
}j;

int main()
{
	printf("%d\n", sizeof(s));
	printf("%d\n", sizeof(j));
	return 0;
}

结果展示

解析
在s中a[19] 的对齐数是 1,b的对齐数是 4,a[19]大小为19个字节,但是不是最大对齐数的整数倍,所以空间为 20个字节。
在j中最大对齐数是 4,所占空间是 80个字节,刚好是 4 的整数倍。

链接

位端、枚举、联合体的相关代码

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/3002673.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存