C语言专题:3.枚举、结构、位域、联合

一、enum(枚举)

        ​ enum 是 C 语言中的一种枚举类型(enumeration),用于定义一组具名的整型常量,增加代码的可读性和可维护性。

基本语法
enum 枚举名 {
    枚举常量1,
    枚举常量2,
    ...
};

        默认从0开始,依次加1增:

enum Weekday {
    MON,   //0
    TUE,   //1
    WED,   //2
    THU,   //3
    FRI,   //4
    SAT,   //5
    SUN    //6
} today1;     //可以在定义枚举类型的同时进行变量的定义

enum Weekday today2; //也可以单独定义变量

        也可以手动赋值:

enum Color {
    RED,        // 0
    GREEN = 5,  // 5
    BLUE        // 6
};

enum Status {
    OK = 0,
    ERROR = 1,
    UNKNOWN = -1
};
用法示例
#include <stdio.h>

enum Status {
    OK = 0,
    ERROR = 1,
    UNKNOWN = -1
};

int main() {
    enum Status s = OK;
 switch(s){
        case OK:
            printf("Everything is fine.\n");
            break;
        case ERROR:
            printf("Somthing is error.\n");
            break;
        case UNKNOWN:
            printf("Somthing is unknown.\n");
            break;
        default:
            break;
    }
    return 0;
}

二、struct(结构)

        ​ struct 是 C 语言中一种用户自定义的数据类型,可以将多个不同类型的变量组合成一个整体。适合用来描述一个实体,比如学生、员工、坐标等。

基本语法
struct 结构体名 {
    类型1 成员名1;  //成员类型可以是基础数据类型,也可以是数组、指针、结构体、函数指针等
    类型2 成员名2;
    ...
};

enum一样,可以在定义struct同时,定义变量,也可以单独定义变量

struct Point {
    int x;
    int y;
} p1, p2;

struct Point p3,p4;
用法示例
#include <stdio.h>

struct Student {
    char name[50];
    int age;
    float score;
};

int main() {
    struct Student s1 = {"Alice", 20, 95.5};

    printf("Name: %s\n", s1.name);
    printf("Age: %d\n", s1.age);
    printf("Score: %.1f\n", s1.score);

    return 0;
}
结构体数组
struct Student students[2] = {
    {"Alice", 20, 95.5},
    {.name = Bob", 
     .age = 21, 
     .score = 88.0}
};

指针与结构体
struct Student s = {"Charlie", 22, 90.0};
struct Student *p = &s;

printf("Name via pointer: %s\n", p->name);  // 用 "->" 访问成员

三、bit-filed(位域)

        C语言的位域(bit-field),一种可以精确控制变量中**每一位或几位**存储方式的结构体特性,常用于嵌入式、协议解析、寄存器映射等场景。

        位域就是在结构体中,通过冒号指定成员所占的位数

struct {
    unsigned int a : 3; // a 占3位
    unsigned int b : 5; // b 占5位
} data1;

struct {
    unsigned int a; // a 占8字节
    unsigned int b; // b 占8字节
} data2;

        这表示 data1 总共只占用 8 位(1 字节),而不是两个完整的 unsigned int(通常是 8 字节)。

基本语法
struct 结构体名 {
    类型 成员名 : 位数;
};

        类型通常是 int, unsigned int,但实际只取它的一部分位数。

        位数决定该成员最多能表示的值范围(例如 3 位能表示 0~7)。

用法示例
#include <stdio.h>

struct Status {
    unsigned int powerOn : 1;    // bit 0
    unsigned int error   : 1;    // bit 1
    unsigned int mode    : 2;    // bits 2-3
    unsigned int reserve : 4;    // bits 4-7
};

int main() {
    struct Status s = {1, 0, 2, 0};

    printf("powerOn = %u\n", s.powerOn);
    printf("error   = %u\n", s.error);
    printf("mode    = %u\n", s.mode);

    return 0;
}
注意事项

        1.位域不能取地址(不能用 &s.mode);

        2.不同编译器对位域排列方式可能不同(大端/小端问题);

        3.类型不能用 char,推荐使用 unsigned int

        4.通常会有字节对齐问题,结构体大小不一定是你位数总和,建议加 #pragma pack(1)__attribute__((packed)) 视平台而定。

备注

  #pragma pack(1)__attribute__((packed)) 使用、

        C语言为了提高访问效率,会对结构体成员进行自动对齐(如按 4 字节、8 字节),可能会插入填充字节(padding)

例如:

struct A {
    char a;   // 1字节
    int b;    // 4字节
};

        这会占用 8字节(1字节char + 3字节padding + 4字节int),而不是5字节。

#pragma pack(1):编译器指令(Visual Studio/GCC兼容):

#pragma pack(1)  // 结构体内成员按1字节对齐
struct A {
    char a;
    int b;
};
#pragma pack()   // 恢复默认对齐

__attribute__((packed)):GCC/Clang专用语法

struct __attribute__((packed)) A {
    char a;
    int b;
};

以上两种做法均可强制去掉结构体内的 padding。

四、union(联合)

        ​ union(联合体)是一种特殊的结构体,它的所有成员共享同一块内存空间。也就是说,在同一时间,只能使用其中的一个成员。

基本语法
union 联合体名 {
    数据类型1 成员1;
    数据类型2 成员2;
    ...
};
用法示例
#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 = 3.14;
    printf("data.f = %.2f\n", data.f);  // 这时 data.i 的值会被覆盖

    return 0;
}

struct 的区别

union data3{
 unsigned  char a;
 unsigned  int b;
}

struct data4{
 unsigned  char a;
 unsigned  int b;
}

 

特性structunion
内存分配每个成员各占一块独立内存所有成员共用同一块内存
总大小所有成员大小之和(考虑对齐)最大的成员大小
同时存储多个值否(只能存一个)
应用场景一组信息同时存在,比如学生信息多种数据格式共存但不会同时使用
union Test {
    int a;       // 4字节
    short b;     // 2字节
    char c;      // 1字节
};
// union Test 的大小 = 4(最大成员大小)
实用场景

1.内存优化

        在嵌入式系统/协议解析中,不同数据类型共用一段内存,可以节省空间。

2.类型转换(低层次实现)

        比如浮点转整型等:

union {
    float f;
    int i;
} u;

u.f = 3.14;
printf("Float 3.14 as int: %d\n", u.i);

3.协议解析 / 寄存器映射

            一个字段可能有多种解释方式,可以通过 union 提供多种视图。

    注意事项
    • 不能同时使用多个成员,因为它们共用内存;

    • 不要依赖某个成员赋值后再访问另一个成员的值(除非你明确知道内存布局);

    • unionstruct 可以嵌套使用。

    五、typedef

            ​ typedef 是 C 语言中常用的关键字,用于给已有类型定义一个新的别名,让代码更简洁、更易读。

    基本语法
    typedef 原类型 新名字;
    
    简单示例
    //结构体示例
    typedef struct {
        char name[20];
        int age;
    } Person;
    Person p1;  // 不需要再写 struct 了,代码更简洁
    
    //基本类型示例
    typedef unsigned int uint;
    uint age = 25;  // 等价于 unsigned int age = 25;
    
    //函数指针示例
    typedef int (*Operation)(int, int);
    
    int add(int a, int b) { return a + b; }
    
    Operation op = add;
    int result = op(2, 3);  // 调用函数指针
    
    
    typedef 和 #define 区别
    对比点typedef#define
    是否检查类型编译器识别类型预处理阶段替换
    是否调试友好能查看类型信息只是文本替换
    建议用途建议用于定义类型别名建议用于宏常量定义

    总结

    • typedef 可以让结构体、函数指针、数组等复杂类型更简洁;

    • 常用于提升可读性和跨平台移植性(比如 uint32_t 就是 typedef 的);

    • struct 一起用最常见。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    代码与烙铁

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

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

    余额充值