C基础第10课 struct 和 union 分析

本文探讨了不同编译器下空结构体的行为,gcc允许空结构体并分配0空间,而bcc和vc编译器则禁止。同时,介绍了柔性数组的概念,其大小为0,但可通过动态分配内存来使用。最后,利用联合体判断系统的大/小端模式。

学习自狄泰软件学院唐佐临老师C语言课程,文章中图片取自老师的PPT,仅用于个人笔记。


实验1 ~3 :不同的编译器对空结构体的规定不一样 gcc编译器允许空结构体存在,并且占用空间为0,而bcc 以及 vc 编译器不允许定义空结构体,他们认为空结构体没有意义。

实验4 柔型数组的大小是0
实验5 柔型数组的使用
实验6 通过联合体 union 判断系统的大小端


在这里插入图片描述

实验1 :gcc 编译器环境
gcc 编译器环境空结构体以及空结构体所定义的变量占用的内存大小都为0
在这里插入图片描述

实验2 :bcc 编译器环境
bcc编译器不允许空结构体的存在
在这里插入图片描述

实验3 : vc编译器环境

vc编译器环境也是不允许空结构体存在的

在这里插入图片描述

在这里插入图片描述

实验4 柔型数组的大小是0

在这里插入图片描述

在这里插入图片描述

实验5 柔型数组的使用

#include <stdio.h>
#include <malloc.h>

struct SoftArray
{
    int len;
    int array[];
};

struct SoftArray* create_soft_array(int size)
{
    struct SoftArray* ret = NULL;
    
    if( size > 0 )
    {
        ret = (struct SoftArray*)malloc(sizeof(struct SoftArray) + sizeof(int) * size);
        
        ret->len = size;
    }
    
    return ret;
}

void delete_soft_array(struct SoftArray* sa)
{
    free(sa);
}

void func(struct SoftArray* sa)
{
    int i = 0;
    
    if( NULL != sa )
    {
        for(i=0; i<sa->len; i++)
        {
            sa->array[i] = i + 1;
        }
    } 
}

int main()
{
    int i = 0;
    struct SoftArray* sa = create_soft_array(10);
    
    func(sa);
    
    for(i=0; i<sa->len; i++)
    {
        printf("%d\n", sa->array[i]);
    }
    
    delete_soft_array(sa);
    
    return 0;
}


mhr@ubuntu:~/work/C$ 
mhr@ubuntu:~/work/C$ 
mhr@ubuntu:~/work/C$ gcc test1.c 
mhr@ubuntu:~/work/C$ 
mhr@ubuntu:~/work/C$ ./a.out 
1
2
3
4
5
6
7
8
9
10
mhr@ubuntu:~/work/C$ 
mhr@ubuntu:~/work/C$ 

在这里插入图片描述

在这里插入图片描述
如果在小端模式的系统 打印会输出 1,1会在低地址存储低位空间,这个时候 c 这个成员变量只占用一个字节,显然 c 占用了联合体低地址的一个存储的空间,故输出 1

如果在大端模式的系统 打印会输出 0,因为1存储在高地址的存储空间,存储结构如上图

不管系统的大小端模式是大端还是小端,我们这个联合体的成员变量c都是取 低地址空间数据,c是从内存的低地址上取数据。

实验6 : 判断系统的大小端

在这里插入图片描述

输出为1,说明1存储在最大存储空间的低位,所以我们的系统是小端模式。

在这里插入图片描述

<think>好的,用户现在问的是C语言中structunion的区别。之前他们问过enum,可能现在在学习C语言的数据结构,想要更全面地了解这些复合数据类型的不同之处。首先,我需要回顾structunion的基本定义用法,然后找出它们的关键区别。 用户可能已经知道structunion都是用来组合多个成员的数据类型,但不太清楚它们内在的区别应用场景。需要从内存分配、成员访问、使用场景等方面进行对比。要注意用例子来说明,这样更直观。 struct每个成员都有独立的内存空间,而union的所有成员共享同一块内存。这点很重要,所以内存占用方面struct是各成员之union是最大成员的大小。比如struct里intchar的话,总大小至少是int的大小加上char的大小,再加上可能的对齐填充。而union的话,只占用最大成员的大小,比如intchar的union,大小就是int的大小。 然后成员的访问上,struct可以同时访问所有成员,union同一时间只能有效存储一个成员的值,修改一个成员会影响其他成员的值。比如例子中的union,修改了i之后,f的值就会被覆盖,可能变成无意义的数据。 接下来要考虑用户可能的疑问,比如什么时候用struct,什么时候用unionstruct适合需要同时保存多个相关数据的情况,比如学生的姓名、年龄、成绩。而union适合需要节省内存或者同一时间只使用一个成员的场景,比如处理不同类型的数据或者做类型转换。 另外,对齐方式的不同可能也是需要注意的地方。struct会有对齐填充,而union的对齐取决于最大成员的对齐需求。不过这部分可能对初学者来说稍微复杂,可以简要提及,重点还是放在内存使用成员访问的区别上。 还要提到初始化的问题,struct可以初始化所有成员,而union只能初始化第一个成员。这在C语言的语法中是一个区别点,需要举例说明。 安全性方面,union因为共享内存,如果错误地访问了未赋值的成员,会导致未定义行为,这也是需要注意的地方。而struct每个成员独立,不会有这种问题。 可能用户在实际使用中会遇到如何选择的问题,所以需要给出明确的场景建议。比如网络协议中的数据包,不同字段同时存在用struct,而同一时间只有一种类型的字段用union。 最后总结两者的区别,帮助用户形成清晰的对比表格,方便记忆。同时提醒用户在使用union时要小心数据覆盖的问题,确保正确的成员被访问。</think>好的!C语言中的 `struct`(结构体) `union`(联合体)都是用于组合多个成员变量的复合数据类型,但它们在内存分配、成员访问方式及使用场景上有显著区别。以下是详细的对比分析: --- ### **1. 内存分配方式** | **特性** | **`struct`** | **`union`** | |--------------|---------------------------------------|---------------------------------------| | **内存分配** | 每个成员拥有独立的内存空间 | 所有成员共享同一块内存空间 | | **总大小** | 各成员大小之(考虑内存对齐) | 等于最大成员的大小(考虑内存对齐) | - **示例**: ```c // struct示例:内存总大小 >= sizeof(int)+sizeof(float)+sizeof(char) struct ExampleStruct { int a; // 4字节 float b; // 4字节 char c; // 1字节 }; // 总大小可能为12字节(对齐到4字节边界) // union示例:内存总大小等于最大成员的大小(float的4字节) union ExampleUnion { int i; // 4字节 float f; // 4字节 char c; // 1字节 }; // 总大小为4字节 ``` --- ### **2. 成员访问** | **特性** | **`struct`** | **`union`** | |--------------|---------------------------------------|---------------------------------------| | **访问方式** | 可同时访问所有成员 | 同一时间只有一个成员有效 | | **覆盖风险** | 无 | 修改一个成员可能覆盖其他成员的值 | - **示例**: ```c union Data { int i; float f; }; union Data data; data.i = 10; // 写入int printf("%d\n", data.i); // 输出10 data.f = 3.14; // 覆盖之前存储的int值 printf("%f\n", data.f); // 输出3.14,但data.i的值已被破坏 ``` --- ### **3. 使用场景** | **特性** | **`struct`** | **`union`** | |--------------|---------------------------------------|---------------------------------------| | **典型场景** | 需要同时存储多个相关数据 | 节省内存,或同一时间仅需一个成员有效 | | **例子** | 学生信息(姓名、年龄、成绩) | 网络协议解析、类型转换、硬件寄存器访问 | - **`struct` 适用场景**: ```c struct Student { char name[20]; int age; float score; }; struct Student s = {"Alice", 18, 95.5}; // 同时存储所有字段 ``` - **`union` 适用场景**: ```c // 处理不同类型的数据(如解析二进制协议) union Packet { int intVal; float floatVal; char bytes[4]; }; union Packet p; memcpy(p.bytes, rawData, 4); // 通过不同成员解释同一段内存 ``` --- ### **4. 初始化与赋值** | **特性** | **`struct`** | **`union`** | |--------------|---------------------------------------|---------------------------------------| | **初始化** | 可初始化所有成员 | 只能初始化第一个成员 | | **赋值** | 各成员独立赋值 | 赋值一个成员会影响其他成员的值 | - **初始化示例**: ```c // struct初始化所有成员 struct Point { int x; int y; }; struct Point p1 = {10, 20}; // 合法 // union只能初始化第一个成员 union Value { int i; float f; }; union Value v1 = {5}; // 合法,i=5,f的值未定义 union Value v2 = {.f=3.14}; // C99后允许指定成员初始化 ``` --- ### **5. 安全性对比** | **特性** | **`struct`** | **`union`** | |--------------|---------------------------------------|---------------------------------------| | **类型安全** | 高(成员独立,无覆盖风险) | 低(需开发者确保成员访问逻辑正确) | | **常见错误** | 对齐问题(填充字节导致空间浪费) | 误用成员导致数据覆盖 | --- ### **总结** - **`struct`**: 适用于需要同时存储多个数据的场景,成员之间相互独立,内存占用较大但安全。 典型应用:对象建模(如学生、坐标)、复杂数据结构(链表、树节点)。 - **`union`**: 适用于节省内存或需灵活解释同一段内存的场景,成员共享内存,需谨慎处理覆盖问题。 典型应用:类型转换、硬件寄存器映射、协议解析。 --- ### **关键区别速查表** | **维度** | **`struct`** | **`union`** | |----------------|-----------------------------|----------------------------| | 内存占用 | 各成员大小之 | 最大成员的大小 | | 成员独立性 | 独立 | 共享 | | 初始化 | 可初始化所有成员 | 只能初始化第一个成员 | | 安全性 | 高 | 低(需手动管理覆盖问题) | | 典型用途 | 数据聚合 | 内存复用或类型转换 | 实际开发中,根据需求灵活选择二者:需要同时保留多个字段用 `struct`,需节省内存或类型转换用 `union`。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ma浩然

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

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

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

打赏作者

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

抵扣说明:

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

余额充值