当前位置: 首页 > news >正文

[学习] C语言结构体与联合体的对比分析

C语言结构体与联合体的对比分析

文章目录

  • C语言结构体与联合体的对比分析
    • 一、定义
      • 1. 结构体(struct)
      • 2. 联合体(union)
    • 二、核心差异对比
    • 三、典型使用场景
      • 1. 结构体场景
      • 2. 联合体场景
    • 四、混合使用案例
      • 1. 网络协议头解析
      • 2. 文件格式解析
      • 3. 图形系统设计
      • 4. 注意事项


一、定义

1. 结构体(struct)

结构体是一种用户自定义的数据类型,它允许将不同类型的数据项组合在一起作为一个整体来处理。结构体的每个成员都有独立的内存空间,成员之间互不干扰。

  • 内存分配方式:结构体的大小等于所有成员大小的总和(考虑内存对齐)。例如在32位系统中,int通常占4字节,float占4字节,char[20]占20字节
  • 声明语法
    struct 结构体标签 {数据类型 成员1;数据类型 成员2;...
    };
    
  • 成员访问:使用点运算符(.)访问成员,如stu.age

示例代码框架:

struct student {char name[20];  // 姓名,占用20字节int age;        // 年龄,通常占用4字节float score;    // 分数,通常占用4字节
};  // 整个结构体在32位系统中通常占用28字节(考虑对齐)// 使用示例
struct student stu1;
strcpy(stu1.name, "张三");
stu1.age = 18;
stu1.score = 89.5;

2. 联合体(union)

联合体是一种特殊的数据类型,它允许在同一内存位置存储不同的数据类型。但任何时候只能使用其中一个成员,所有成员共享同一块内存空间。

  • 内存特性:联合体的大小等于其最大成员的大小
  • 声明语法
    union 联合体标签 {数据类型 成员1;数据类型 成员2;...
    };
    
  • 内存占用:联合体只分配足够容纳最大成员的内存空间

示例代码框架:

union data {int i;      // 占用4字节float f;    // 占用4字节char str[4];// 占用4字节
};  // 整个联合体占用4字节// 使用示例
union data value;
value.i = 10;       // 存储整数
printf("%d", value.i);
value.f = 3.14;     // 存储浮点数,之前存储的整数被覆盖
printf("%f", value.f);

典型应用场景:

  1. 结构体适用于需要同时存储多个相关数据的场景(如学生信息)
  2. 联合体适用于需要节省内存空间,且同一时间只需使用一种类型的场景(如协议解析)

二、核心差异对比

  • 内存分配方式
    结构体采用"内存叠加"方式,每个成员都分配独立的内存空间,且按声明顺序连续排列。例如一个包含int和char的结构体,在32位系统中将占用4+1=5字节(考虑对齐可能为8字节)。
    联合体采用"内存重叠"方式,所有成员共享同一段内存空间,其大小为最大成员所需内存。例如同时包含int和char的联合体,只占用4字节(int所需空间),char将使用int的部分存储空间。

  • 访问特性
    结构体支持同时访问所有成员,各成员的值互不影响。例如可以同时读取student结构体的name和age字段。
    联合体同一时间仅能有效访问一个成员,修改任一成员都会影响其他成员的值。如先给union的int成员赋值后,再读取char成员将得到int数据的部分字节。

  • 应用目标
    结构体适用于需要聚合多种数据的场景,如学生信息(学号、姓名、成绩等)、坐标点(x,y,z)等复合数据结构。
    联合体主要用于:1)实现类型转换,如将float的二进制表示拆解为4个byte;2)节省内存空间,如在协议解析时,同一字段可能存储不同类型但不会同时使用。

  • 典型示例

    // 结构体示例
    struct Student {char name[20];int age;float score;
    }; // 各字段独立存储// 联合体示例
    union Data {int i;float f;char str[4];
    }; // 所有字段共享内存
    

三、典型使用场景

1. 结构体场景

结构体常用于需要组合多个不同类型数据的场景,主要应用包括:

  1. 数据库记录存储

    • 可以表示完整的数据库表记录
    • 例如:员工信息(工号、姓名、部门、工资等)
  2. 对象建模

    • 几何图形:坐标点、矩形区域
    • 学生信息:学号、姓名、成绩
    • 商品信息:ID、名称、价格、库存

实验示例详细说明:

#include <stdio.h>// 定义表示二维坐标点的结构体
struct point {int x;  // x坐标int y;  // y坐标
};int main() {// 初始化结构体实例struct point p = {3, 4};// 访问结构体成员并打印printf("坐标: (%d, %d)\n", p.x, p.y);// 修改结构体成员值p.x = 10;p.y = 20;printf("新坐标: (%d, %d)\n", p.x, p.y);return 0;
}

2. 联合体场景

联合体主要用于需要共享内存空间的场景,典型应用包括:

  1. 网络协议解析

    • 解析IP头部、TCP头部等网络协议字段
    • 方便以不同方式访问同一数据
  2. 硬件寄存器访问

    • 访问特殊功能寄存器
    • 既可以整体操作也可以位操作
  3. 类型转换

    • 实现类似变体类型(Variant)的效果
    • 实现数据类型的灵活转换

实验示例详细说明:

#include <stdio.h>// 定义联合体用于整数和字节数组的转换
union converter {int num;        // 4字节整数char bytes[4];  // 4字节数组
};int main() {union converter c;// 赋值整数c.num = 0x12345678;// 通过字节数组访问printf("字节0: %02x\n", c.bytes[0]);  // 低字节printf("字节1: %02x\n", c.bytes[1]);printf("字节2: %02x\n", c.bytes[2]);printf("字节3: %02x\n", c.bytes[3]);  // 高字节// 修改字节影响整数值c.bytes[0] = 0xAA;printf("新整数值: %08x\n", c.num);return 0;
}

四、混合使用案例

结构体和联合体的组合使用在实际编程中非常常见,特别是在需要处理多种数据类型但又需要统一存储结构的场景。下面通过几个具体案例来展示这种组合的实用价值。

1. 网络协议头解析

在网络编程中,经常需要解析不同类型的协议数据包。使用结构体嵌套联合体可以高效地处理这种场景:

// 定义网络数据包结构
struct packet {int type;  // 数据包类型标识union {int int_data;     // 用于传输整数数据float float_data; // 用于传输浮点数据char str_data[64];// 用于传输字符串数据} payload; // 联合体存储不同类型的数据内容
};

使用方法示例:

struct packet pkt;
pkt.type = 1; // 设为整数类型
pkt.payload.int_data = 42; // 存储整数pkt.type = 2; // 设为浮点类型
pkt.payload.float_data = 3.14f; // 存储浮点数

2. 文件格式解析

在处理多种文件格式时,这种模式也非常有用:

struct file_header {char magic[4];  // 文件标识符int version;    // 文件版本union {struct {int width;int height;} image_data;  // 图像文件专用字段struct {int sample_rate;int channels;} audio_data;  // 音频文件专用字段} format_data;
};

3. 图形系统设计

在图形系统中处理不同类型的图形对象:

struct graphic_object {int obj_type; // 1=圆形, 2=矩形, 3=三角形union {struct {float radius;} circle;struct {float width;float height;} rectangle;struct {float base;float height;} triangle;} attributes;
};

4. 注意事项

  1. 使用联合体时需要格外小心类型安全问题
  2. 需要额外的标识字段来指示当前使用的联合体成员
  3. 针对不同平台需要考虑内存对齐问题
  4. 在跨系统通信时要考虑字节序问题

这种设计模式极大地提高了数据结构的灵活性,同时保持了内存使用的高效性。


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


相关文章:

  • 正规网站模板设计crm系统成功案例分享ppt
  • 崇安网站建设百度百家自媒体平台注册
  • 网站制作算什么费用成都百度网站排名优化
  • 哪有做网站的公司培训方案模板
  • 自己做网站要学什么seo实战密码在线阅读
  • 全国中小企业网站汕头seo推广
  • 鼠标右键添加新建某种文件的方法
  • 基于贝叶斯学习方法的块稀疏信号压缩感知算法
  • python做题日记(14)
  • 30-SIM数据交互APDU之-T0、T1
  • RK3588开发笔记-GNSS-RTK模块调试
  • 技术革新,EtherCAT转CAN网关,新能源汽车电池产线再升级
  • 纯血Harmony NETX 5小游戏实践:2048(附源文件)
  • 嵌入式学习笔记DAY36(事务、网页制作、HTTP协议)
  • python的时间管理库whenever的使用
  • 常见的CAN总线协议面试题
  • Vue 中的数据代理机制
  • 【数据大屏】大屏多尺寸屏幕兼容方案(适配任何屏,包括手机)scale
  • 虚拟电厂是什么?来源?发展阶段?
  • UE5.2像素流实现公网访问
  • 如何顺利将电话号码转移到新iPhone?
  • 浏览器拓展-玻璃质感下载管理器
  • 【面板数据】中国与世界各国农产品进出口贸易数据(2015-2024年)
  • OpenLayers 加载Geoserver WMTS服务
  • defineAsyncComponent
  • 大模型在输尿管上段积脓预测与治疗方案制定中的应用研究