位置:首页 > C > C 语言自定义数据类型梳理:枚举、结构体、共用体与 typedef

C 语言自定义数据类型梳理:枚举、结构体、共用体与 typedef

时间:2026-08-24  |  作者:清风无痕  |  阅读:0

目录

  1. 枚举:给一组整型常量起名字
  2. 结构体:把不同类型的数据组织成一个整体
  3. 共用体:多个成员共用同一段内存
  4. typedef:给复杂类型起一个更好用的别名
  5. 怎么区分这四类自定义类型

前言

在 C 语言里,很多初学者会把“自定义类型”只理解成会写语法,但一到实际代码里,就分不清枚举、结构体、共用体和 typedef 到底各自解决什么问题。本文按“定义方式、访问方法、存储特点、适用场景”整理这四类内容,帮助判断什么时候优先考虑可读性,什么时候先看内存布局。

在 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 = 888SUNDAY = 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的使用定位对比图,展示枚举负责命名常量,typedef负责简化类型声明。
枚举与 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:给已有类型起别名,重点是简化声明。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多