C语言之旅:自定义类型(联合和枚举)

目录

一.联合体

1.1 联合体的声明

1.2 联合体的使用

1.3 为什么输出 4呢?

1.4 相同成员的结构体和联合体对比

1.5 联合体大小对比

1.6使用联合体判断大小端

二.枚举类型

2.1枚举类型的例举:

 2.2枚举类型的优点

2.3 枚举类型的使用


在上篇文章中已经介绍了结构体。另外,C语言还提供了另外两种数据类型——联合体(union)和枚举(enum),它们各自具有独特的功能和用途。本文将带你深入了解联合体和枚举的概念、用法以及它们在实际编程中的应用。

一.联合体

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。

但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。

所以联合体也叫:共⽤体。 给联合体其中⼀个成员赋值,其他成员的值也跟着变化。

1.1 联合体的声明

union Un
{
 char c;
 int i;
};

1.2 联合体的使用

#include <stdio.h>
//联合类型的声明 
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义 
 union Un un = {0};
 //计算连个变量的⼤⼩ 
 printf("%d\n", sizeof(un));
 return 0;
}

输出结果:4

1.3 为什么输出 4呢?

 int类型的大小通常是4个字节(byte)。由于联合体的大小至少足够大以容纳其最大的成员,因此Un联合体的大小至少应该是int类型的大小,所以输出为 4。

代码1:

#include <stdio.h>
//联合类型的声明 
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;
}

输出结果:

012FFD0C
012FFD0C
012FFD0C

这段代码输出了三个地址,它们分别是联合体Un的int成员i的地址、char成员c的地址,以及整个联合体变量un的地址。 

 代码2:

#include <stdio.h>
//联合类型的声明 
union Un
{
 char c;
 int i;
};
int main()
{
 //联合变量的定义 
 union Un un = {0};
 un.i = 0x11223344;
 un.c = 0x55;
 printf("%x\n", un.i);
 return 0;
}

输出结果:

11223355

 

 un.i赋值0x11223344,这是一个十六进制数,它会被存储在un联合体所分配的内存中。因为int类型通常占用4个字节,所以0x11223344会被完整地存储在这4个字节中。

然后,代码又对un.c赋值0x55。由于un.c和un.i共享同一块内存,这个赋值会覆盖un.i的最低有效字节(即char类型所占用的字节)。

那么,0x55会覆盖0x11223344的最低字节,变成0x11223355

最后,代码打印un.i的值,由于我们已经修改了它的最低字节,所以输出的是11223355。(小端机器)。

1.4 相同成员的结构体和联合体对比

代码示例:

struct S
{
	char  c;
	int i;
};
struct S s = { 0 };

union Un
{
	char c;
	int i;
};
union Un un = { 0 };

1.5 联合体大小对比

• 联合的大小至少是最⼤成员的⼤⼩。

• 当最大成员大小不是最⼤对⻬数的整数倍的时候,就要对齐到最大对齐数的整数倍。

代码示例:

#include <stdio.h>
union Un1
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	//下⾯输出的结果是什么? 
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}

输出结果:
8
16

由于 char 数组的大小是5个字节,而 int 通常需要4字节对齐,编译器可能会选择增加1个字节的填充(padding),使得整个 union Un1 的大小为8个字节,以满足 int 的对齐要求。 

short c[7] 需要14个字节,这超过了 int 的4个字节,所以 union Un2 的大小将是14个字节。与 union Un1 类似,由于内存对齐的原因,编译器可能会增加额外的填充。在这种情况下,编译器可能会添加2个字节的填充,使 union Un2 的总大小为16个字节。

使用联合体可以节省空间。

1.6使用联合体判断大小端

代码示例:

#include <stdio.h>    
  
int check_sys()    
{    
    union    
    {    
        int i;    
        char c[sizeof(int)]; // 使用字符数组以便访问int的各个字节    
    } un;    
    
    un.i = 1; // 设置int为1    
    
    // 检查int的最低有效字节(在小端系统中应该是1)    
    return *(char *)&un.i == 1; // 如果返回true(非零),则是小端系统;如果返回false(零),则是大端系统    
}    
  
int main()    
{    
    if (check_sys()) {    
        printf("这是一个小端系统。\n");    
    } else {    
        printf("这是一个大端系统。\n");    
    }    
    return 0;    
}

二.枚举类型

枚举类型(enum)是一种用户定义的数据类型,枚举(enum)顾名思义就是⼀⼀列举。把可能的取值⼀⼀列举。

2.1枚举类型的例举:

例如:

一周的星期⼀到星期日是有限的7天,可以一一列举

 //星期
enum Weekday 
{  
    Sunday,  
    Monday,  
    Tuesday,  
    Wednesday,  
    Thursday,  
    Friday,  
    Saturday  
};

性别有:男、女、保密,也可以一一列举 

//性别
enum Sex 
{  
    Male,  
    Female,  
    Cfidntl  
};

 2.2枚举类型的优点

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

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

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

4. 使方便便,一次可以定义多个常量

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

2.3 枚举类型的使用

#include <stdio.h>  
  
 
enum Color 
{  
    Red,  
    Green,  
    Blue,     
};  
  
int main()
 {  
    // 声明一个Color类型的变量  
    enum Color myColor;  
  
  
    myColor = Red;  
    switch (myColor) {  
        case Red:  
            printf("颜色是红色。\n");  
            break;  
        case Green:  
            printf("颜色是绿色。\n");  
            break;  
        case Blue:  
            printf("颜色是蓝色。\n");  
            break;  
        default:  
            printf("未知的颜色。\n");  
            break;  
    }  
      
    return 0;  
}

 注意,在C语言中,枚举常量默认从0开始,并且每个后续常量比前一个常量大1。因此,在这个例子中,Red的值为0,Green的值为1,Blue的值为2

当然也以拿整数给枚举变量赋值。在C语⾔中是可以的,但是在C++是不行的,C++的类型检查⽐ 较严格。

代码示例:

enum Color 
{  
    Red = 1,  
    Green = 2,  
    Blue = 3  
};

  • 31
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值