C语言精讲-10
1.共同体(Union 结构)
1.1共用体概述
在某些场景下,我们需要一种能在不同场合表示不同数据类型的数据结构。以学生“成绩”为例,它可能是整数形式(如 80、90),可能是字符形式(如 ‘A’、‘B’),也可能是浮点数形式(如 80.5、60.5)。
在 C 语言里,共用体类型(Union 结构)能自定义灵活可变的数据结构。共用体内部可包含多种属性,但在同一时刻,只能有一个属性有效。这是因为所有属性都存于同一内存地址,后写入的属性会覆盖之前的属性。这种设计的最大优势在于节省内存空间。
虽然“共用体”和“结构体”的定义形式相近,但其含义大不相同。结构体变量占用的内存长度是各成员所占内存长度之和,每个成员都有独立的内存单元;而共用体变量所占内存长度等于其最长成员的长度,所有成员共享同一内存区域。
1.2共用体的基本使用
#include <stdio.h>
// 定义一个共用体来存储成绩
union Score {
int int_score;
char char_score;
float float_score;
};
int main() {
union Score s;
// 存储整数成绩
s.int_score = 85;
printf("Integer score: %d\n", s.int_score);
// 存储字符成绩
s.char_score = 'B';
printf("Character score: %c\n", s.char_score);
// 存储浮点数成绩
s.float_score = 80.5;
printf("Float score: %.2f\n", s.float_score);
return 0;
}
1.3案例演示
1.在不同数据类型间转换
#include <stdio.h>
// 定义一个共用体用于数据类型转换
union DataConverter {
int integer;
char bytes[4];
};
int main() {
union DataConverter converter;
converter.integer = 0x12345678;
// 输出每个字节
for (int i = 0; i < 4; i++) {
printf("Byte %d: 0x%02X\n", i, (unsigned char)converter.bytes[i]);
}
return 0;
}
2.在结构体中使用共用体
#include <stdio.h>
#include <string.h>
// 定义一个共用体
union Value {
int int_value;
float float_value;
char string_value[20];
};
// 定义一个结构体,包含共用体
struct Data {
int type; // 0: int, 1: float, 2: string
union Value value;
};
void printData(struct Data data) {
switch (data.type) {
case 0:
printf("Integer value: %d\n", data.value.int_value);
break;
case 1:
printf("Float value: %.2f\n", data.value.float_value);
break;
case 2:
printf("String value: %s\n", data.value.string_value);
break;
default:
printf("Invalid type\n");
}
}
int main() {
struct Data data;
// 存储整数
data.type = 0;
data.value.int_value = 100;
printData(data);
// 存储浮点数
data.type = 1;
data.value.float_value = 3.14;
printData(data);
// 存储字符串
data.type = 2;
strcpy(data.value.string_value, "Hello");
printData(data);
return 0;
}
3.使用枚举判断是大端存储还是小端存储
在计算机系统中,数据存储存在大端字节序(Big Endian)和小端字节序(Little Endian)两种方式。大端字节序是指数据的高位字节存于低地址,低位字节存于高地址;小端字节序则相反,数据的低位字节存于低地址,高位字节存于高地址。下面我会借助枚举类型判断系统采用的是大端存储还是小端存储。
#include <stdio.h>
// 定义一个结构体用于判断字节序
struct EndiannessChecker {
unsigned char byte1 : 8;
unsigned char byte2 : 8;
unsigned char byte3 : 8;
unsigned char byte4 : 8;
};
// 函数用于判断字节序
void check_endianness() {
union {
unsigned int num;
struct EndiannessChecker checker;
} u;
u.num = 0x12345678;
if (u.checker.byte1 == 0x78) {
printf("This system uses little-endian byte order.\n");
} else if (u.checker.byte1 == 0x12) {
printf("This system uses big-endian byte order.\n");
} else {
printf("Unexpected byte order result.\n");
}
}
int main() {
check_endianness();
return 0;
}
2.枚举(enum)
在 C 语言里,枚举(enum)属于用户自定义的数据类型,其作用是把一组相关的常量整合在一起。这些常量会被赋予整数值,默认情况下,首个枚举常量的值为 0,后续常量的值依次递增 1。不过,你也能为枚举常量手动指定特定的值。枚举类型可以增强代码的可读性与可维护性,让代码更具语义化。
使用案例
1.表示一周的天数
#include <stdio.h>
// 定义枚举类型表示一周的天数
enum Weekdays {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
};
int main() {
// 输出每个枚举常量对应的值
printf("MONDAY: %d\n", MONDAY);
printf("TUESDAY: %d\n", TUESDAY);
printf("WEDNESDAY: %d\n", WEDNESDAY);
printf("THURSDAY: %d\n", THURSDAY);
printf("FRIDAY: %d\n", FRIDAY);
printf("SATURDAY: %d\n", SATURDAY);
printf("SUNDAY: %d\n", SUNDAY);
return 0;
}
2.表示颜色
#include <stdio.h>
// 定义枚举类型表示颜色
enum Colors {
RED = 1,
GREEN = 2,
BLUE = 4,
YELLOW = RED | GREEN,
MAGENTA = RED | BLUE,
CYAN = GREEN | BLUE,
WHITE = RED | GREEN | BLUE
};
int main() {
// 输出每个枚举常量对应的值
printf("RED: %d\n", RED);
printf("GREEN: %d\n", GREEN);
printf("BLUE: %d\n", BLUE);
printf("YELLOW: %d\n", YELLOW);
printf("MAGENTA: %d\n", MAGENTA);
printf("CYAN: %d\n", CYAN);
printf("WHITE: %d\n", WHITE);
return 0;
}
3.在函数中使用枚举
#include <stdio.h>
// 定义枚举类型表示交通信号灯状态
enum TrafficLight {
RED_LIGHT,
YELLOW_LIGHT,
GREEN_LIGHT
};
// 函数根据交通信号灯状态输出信息
void print_traffic_light_status(enum TrafficLight light) {
switch (light) {
case RED_LIGHT:
printf("Stop! The light is red.\n");
break;
case YELLOW_LIGHT:
printf("Get ready! The light is yellow.\n");
break;
case GREEN_LIGHT:
printf("Go! The light is green.\n");
break;
default:
printf("Invalid traffic light status.\n");
}
}
int main() {
// 调用函数并传入不同的枚举值
print_traffic_light_status(RED_LIGHT);
print_traffic_light_status(YELLOW_LIGHT);
print_traffic_light_status(GREEN_LIGHT);
return 0;
}
3.typedef 的使用
在 C 语言里,我们能够为数据类型赋予新的别名,这就如同给人取 “绰号”。这样做并非为提升程序运行效率,而是为了让编码更加便捷。
struct student{} ; 定义一个结构体变量: struct student s1;
typedef struct student{}st; 定义一个结构体变量: st s1; 就简单了很多
使用格式: typedef 类型名 别名;
typedef int Integer; //用Integer作为int类型别名,作用与int相同