初识C语言·自定义类型(1)

本文详细解析了联合体和枚举类型的声明、特点,如共用空间、大小计算、内存对齐,以及枚举的优点,如可读性、类型检查和调试便利性。
摘要由CSDN通过智能技术生成

目录

1 联合体类型的声明

2 联合体的特点

3 联合体的大小计算

4 枚举类型类型的声明

5 枚举的优点


1 联合体类型的声明

联合体,顾名思义,是多个对象连在一起的,即联合体的成员都是共用空间的,所以联合体也叫做共用体,既然是共用一块空间,那么改变其中一个成员的值的时候,其他对象的值也会随着改变。

联合体用到的关键字是union。

先介绍第一个特性,共用一块空间,

union un
{
	char a;
	int b;
};
int main()
{
	union un tem;
	printf("%zd\n", sizeof(tem));
	return 0;
}

联合体里面有一个字符类型,一个整型,整型占4个字节,字符占1个字节,所以会占4个字节。

即编译器只会给占内存最大的成员分配空间。

介绍第二种特性,共用一块空间。

union un
{
	char a;
	int b;
};
int main()
{
	union un tem;
	printf("%zd\n", sizeof(tem));
	tem.b = 0x11223344;
	printf("%x %x", tem.a, tem.b);
	return 0;
}

因为vs是小端存储,所以存的16进制的11223344,所以存的顺序是44332211,那么a的值就是44,b的值就是11223344。

前面提到的可以用联合体判断机器是大端机器还是小端机器,就是完美利用了联合体的特点,

union un
{
	char a;
	int b;
};
int main()
{
	union un tem;
	tem.b = 0x11223344;
	if (tem.a == 11)
	{
		printf("大端");
	}
	else
	{
		printf("小端");
	}
	return 0;
}

在写联合体的时候,需要注意花括号后面要有分号,定义联合体变量的时候,是需要写union un的,当然,可以直接在花括号后面写,那种写法是表示定义,如下:
 

union un
{
	char a;
	int b;
}tem1,tem2;

2 联合体的特点

联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合 ⾄少得有能⼒保存最⼤的那个成员)。

先看一段代码

union Un
{
	char c;
	int i;
};
int main()
{
	union Un un = { 0 };
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
	printf("%p\n", &un);
	return 0;
}

问打印的结果都是一样的吗?

没错是的,这就是说明联合体的存放元素的时候都是从同一块空间开始存的。

因为空间共用,所以我们要修改前文的11223344中的44也是可以的,这里请自行实验咯。

这里稍微引入一点结构体的知识,我们比较一下在相同的成员情况下,结构体和联合体占用的内存多少。

union Un
{
	int a;
	char c;
	int i;
}un;
struct St
{
	int a;
	char c;
	int i;
}st;
int main()
{
	printf("%zd\n", sizeof(un));
	printf("%zd\n", sizeof(st));
	return 0;
}

可以看到,成员有两个char,一个int类型的,所以联合体的大小应该是4,那么结构体的大小是?

是12?!对,确实是12,至于为什么,就下一篇再介绍了,这里涉及到的知识是内存对齐。


3 联合体的大小计算

联合体的大小就一定是最大成员的大小吗?举个例子。

union Un1 
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	printf("%zd\n", sizeof(union Un1));
	printf("%zd\n", sizeof(union Un2));
	return 0;
}

按刚才的来讲,Un1的大小应该是5,Un2的大小应该是14,让我们来揭晓谜底。

结果是8 16,这是因为最大成员的大小不是最大对齐数的整数倍的时候,系统就会浪费空间去凑到最大对齐数的整数倍,且听下回分解。


4 枚举类型类型的声明

现实生活中比如星期1到星期7,性别,三原色,我们都是可以一一列举的,这就是枚举,将有限个数的元素一一列举出来。

枚举用到的关键字是enum,里面的成员叫做枚举常量,如下:

enum Color
{
	Red,
	Blue,
	yellow
};

注意格式,枚举变量中间是用逗号进行隔开的,且最后是没有分号的,但是花括号的后面依旧是有分号的。

这是枚举的声明,那枚举常量有没有值呢?

答案是有的,并且看来是层层递增的,那么我们如果附上初值呢?

enum Color
{
	Red = 1,
	Blue = 3,
	yellow
};
int main()
{
	printf("%d ", Red);
	printf("%d ", Blue);
	printf("%d ", yellow);
	return 0;
}

所以可以得出结论,枚举常量的值是递增的,修改之后也是递增的,且默认从0开始递增。

既然枚举常量是整型,是常量,我们可以应用到switch语句里面吗?

enum Color
{
	Red,
	Blue,
	yellow
};
int main()
{
	switch (Blue)
	{
	case 0:
		printf("0");
		break;
	case 1:
		printf("1");
		break;
	case 2:
		printf("2");
		break;
	default:
		break;
	}
	return 0;
}

当然是可以的,最后的结果就是1。

枚举常量也是可以用于给枚举常量赋值的。

enum Color clr = Blue;

像这样,但是在C语言里面是可以用整数给枚举常量赋值的,c++里面是不可以的,因为c++的类型检查比较严格,会认为这是两种不同的类型不能进行赋值。


5 枚举的优点

枚举的优点(和define相比):

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。

3. 便于调试,预处理阶段会删除 #define 定义的符号

4. 使⽤⽅便,⼀次可以定义多个常量

5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤


感谢阅读!

  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值