共用体
定义:
- 共用体是一个用户自定义的类型,包含多个不同类型的成员,但在同一时间只能存储其中一个成员的值。
- 共用体的声明类似于结构体,但使用关键字
union
。
union Example {
int i;
float f;
char c;
};
内存分配:
- 共用体的大小等于其最大成员的大小。例如,如果共用体包含一个
int
(4字节)、一个float
(4字节)和一个char
(1字节),则共用体的大小为4字节。 - 这种存储方式允许不同类型的数据在同一块内存区域中存储,从而节省内存。
访问成员:
- 可以通过使用点运算符(.)访问共用体的成员。由于所有成员共享同一内存,因此在任何时候只能访问最后写入的成员。
- 访问未定义的成员值是未定义行为
union Example e;
e.i = 42;
printf("%d\n", e.i); // 输出:42
e.f = 3.14f;
printf("%f\n", e.f); // 输出:3.140000
用途:
- 节省内存:在内存有限或需要高效内存使用的嵌入式系统中,共用体非常有用。
- 类型转换:共用体可以用来在不同类型之间进行低级别的类型转换。例如,可以通过共用体将浮点数的位模式解释为整数类型。
共用体与结构体的区别
- 内存分配:结构体的大小是其所有成员的大小总和,而共用体的大小是其最大成员的大小。
- 成员访问:结构体中的所有成员都有独立的内存空间,可以同时访问;共用体只能同时存储一个成员的值。
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data data;
data.i = 10;
printf("data.i : %d\n", data.i);
data.f = 220.5;
printf("data.f : %f\n", data.f);
strcpy(data.str, "C Programming");
printf("data.str : %s\n", data.str);
return 0;
}
共用体 Data
依次存储了整数、浮点数和字符串。最后访问的成员 data.str
,覆盖了之前的值。
typedef
typedef
是 C 语言中的一个关键字,用于为现有的数据类型定义新的类型名称。它的主要目的是提高代码的可读性、可维护性和简化复杂类型的使用
typedef existing_type new_type_name;
existing_type
是已经存在的类型,可以是基本数据类型(如int
、float
)或复合类型(如结构体、共用体、指针等)。new_type_name
是新的类型名,用户可以在代码中使用它来替代existing_type
。
简化复杂类型的定义:
- 对于复杂的类型声明(如指向函数的指针),使用
typedef
可以使代码更简洁和易读typedef void (*func_ptr)(int, int);
-
上述定义创建了一个新的类型
func_ptr
,它表示一个指向以两个int
作为参数、返回类型为void
的函数的指针。 -
提高代码的可读性:
- 使用
typedef
可以为类型创建更具描述性的名称,从而使代码更易于理解。typedef unsigned long ulong;
将
unsigned long
类型定义为ulong
,使其在使用时更加简洁 -
提高代码的可维护性:
- 在需要改变类型定义的情况下,只需修改
typedef
的定义,而不需要修改代码中所有出现该类型的地方。typedef int size; size x, y;
若以后需要将
size
类型改为long
,只需修改typedef int size;
为typedef long size;
。
与结构体、共用体和枚举配合使用:
- 使用
typedef
可以为结构体、共用体和枚举类型定义新的名称,简化它们的使用。
typedef struct {
int x;
int y;
} Point;
Point p1;
定义了一个结构体类型 Point
,并使用它来声明变量 p1
。
typedef
仅仅是创建了类型的别名,它不会创建新的类型。类型别名在编译器看来与原类型完全相同。typedef
的定义通常放在头文件中,以便在多个源文件中共享。
位运算
位运算符
-
按位与 (
&
):
-
- 对应位都为1时,结果为1;否则为0。
- 常用于清零操作、保留某些位。
int a = 5; // 0101 int b = 3; // 0011 int result = a & b; // 结果:0001,即1
2.按位或 (
|
):
-
对应位有一个为1,结果即为1。常用于设置某些位。
int a = 5; // 0101
int b = 3; // 0011
int result = a | b; // 结果:0111,即7
按位异或 (^
):
- 对应位不同则结果为1,相同则为0。
- 常用于翻转某些位、比较两个值是否不同。
int a = 5; // 0101
int b = 3; // 0011
int result = a ^ b; // 结果:0110,即6
按位取反 (~
):
- 对每个二进制位进行取反操作,即0变1,1变0。
int a = 5; // 0101
int result = ~a; // 结果:1010(补码表示-6)
左移 (<<
):
- 将位向左移动指定的位数,右边补0。
- 相当于乘以2的若干次幂。
int a = 5; // 0101
int result = a << 1; // 结果:1010,即10
int a = 5; // 0101
int result = a >> 1; // 结果:0010,即2
- 将位向右移动指定的位数。
- 如果是无符号数,左边补0;如果是有符号数,行为依赖于编译器(有符号位扩展和逻辑右移两种可能)。