在 C 语言里,很多初学者会把“自定义类型”只理解成会写语法,但一到实际代码里,就分不清枚举、结构体、共用体和 typedef 到底各自解决什么问题。本文按“定义方式、访问方法、存储特点、适用场景”整理这四类内容,帮助判断什么时候优先考虑可读性,什么时候先看内存布局。
枚举:给一组整型常量起名字
枚举用于定义一组相关常量,把数字换成有语义的名字。
枚举怎么定义
#include
enum weekday
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY = 888,
SUNDAY = 666
};
int main()
{
enum weekday day = MONDAY;
}
enum weekday
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
} day = MONDAY, day2;
int main()
{
printf("%d", day); //0
}
enum
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
} day = MONDAY;
int main()
{
enum Bool
{
FALSE,
TRUE
};
}
枚举值有哪些规则
- 同一枚举中的值必须唯一。
- 枚举值必须是整数类型,通常按
int处理。 - 未手动赋值时,从
0开始递增。 - 可自定义值,如
SATURDAY = 888、SUNDAY = 666。
结构体:把不同类型的数据组织成一个整体
结构体用于组合多字段数据。

结构体的定义方式
struct 类型名称
{
成员类型 成员名称;
成员类型 成员名称;
....
};
struct 类型名称 变量名;
struct Student
{
int id;
char *name;
} s1 = {1, "小明"};
如何访问结构体成员
printf("%d %s", s1.id, s1.name);
struct Student s2 = {2, "小王"};
struct Student *p = &s2;
printf("%d %s", (*p).id, (*p).name);
printf("%d %s", p->id, p->name);
p->id 是 (*p).id 的简写。
为什么结构体大小不等于成员简单相加
原因是内存对齐。
- 每个类型都有自己的对齐长度。
- 32 位环境下默认限制最大对齐值常见为 4 字节,Windows 多为 16 字节。
- 如果类型大小没超过默认对齐长度,对齐长度取类型本身大小。
- 如果超过限制,对齐长度取默认对齐长度。
对齐长度 = 类型大小 < 默认对齐长度 类型大小 : 默认对齐长度- 整个结构体的对齐长度取最大成员的对齐长度。
- 结构体总大小通常是该最大对齐长度的整数倍。
struct Outer
{
char a;
struct Inner
{
char b;
int c;
} inner;
};
共用体:多个成员共用同一段内存
共用体与结构体语法相似,但所有成员共享同一块内存。

共用体的定义与赋值
union 类型名称
{
成员类型 成员名称;
成员类型 成员名称;
....
}
union data
{
int a;
double b;
char c;
};
int main()
{
union data d0;
d0.a = 1;
d0.c = 'A';//会把a覆盖,d0.a的值变为65
union data d1 = {1};//给第一个成员赋值
union data d2 = {.b = 3.14};//给成员b赋值
printf("%d", d0.a);//65
return 0;
}
后一次写入会覆盖之前成员内容。
访问方式和存储大小
d0.a;
d0.b;
d0.c;
union data *p = &d1;
printf("%d", p->a);
共用体大小通常由最大成员决定,适合同一时刻只使用一种表示方式的场景。
typedef:给复杂类型起一个更好用的别名
typedef 不创建新类型,只给已有类型起别名。

typedef 和 #define 的区别
#define在预处理阶段执行;typedef在编译阶段参与类型处理。#define只是文本替换,不做类型检查;typedef会接受类型检查。#define没有通常意义上的作用域概念;typedef具有作用域。
typedef 常见用法
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef int Int_array[];
typedef double Double_array5[5];
typedef double Avg_function(int, int);
typedef int *Int_ptr;
typedef char *String;
typedef int (*Int_arr_ptr)[];
typedef double (*Avg_function_ptr)(int, int);
struct User
{
char *name;
int age;
};
typedef struct User VipUser;
typedef struct Person
{
char *name;
int age;
} Person;
typedef struct
{
char *name;
double score;
} Student;
typedef union
{
char a;
double b;
} Score;
typedef enum
{
MALE,
FEMALE,
ELSE
} Gender;
怎么区分这四类自定义类型
- 枚举:给有限整型常量命名,重点是可读性。
- 结构体:组合多个不同成员,重点是组织数据。
- 共用体:多个成员复用同一块内存,重点是共享存储。
- typedef:给已有类型起别名,重点是简化声明。







