• C语言共用体详解


    共用体解释

    共用体(Union)是一种特殊的数据类型
    它允许在同一个内存位置存储不同的数据类型。
    共用体的所有成员共享同一块内存空间,
    因此同一时间只能存储其中一个成员的值。

    共用体的定义和结构体类似,使用关键字union,后面跟着成员列表。
    每个成员可以是不同的数据类型,
    但共用体的所有成员都共享同一块内存空间,大小取决于最大的成员

    共用体的成员可以通过点操作符(.)或箭头操作符(->)来访问。

    共用体的主要特点如下:

    1. 共用体的大小取决于最大的成员的大小。
    2. 共用体的成员共享同一块内存空间只能同时存储其中一个成员的值
    3. 对共用体的任何成员的修改都会影响到其他成员
    4. 共用体的成员可以具有不同的数据类型,但它们在内存中的起始位置是相同的

    共用体的主要用途有:

    1. 节省内存空间:当多个成员变量不会同时使用,但需要共享同一块内存空间时,可以使用共用体来节省内存。
    2. 数据类型转换:共用体可以用于不同类型之间的转换,通过存储一个成员变量,然后通过另一个成员变量来读取转换后的值。

    需要注意的是,由于共用体的成员共享同一块内存空间,因此在使用共用体时需要谨慎处理成员的赋值和读取操作,以免出现意外的结果。

    代码说明

    #include 
    
    // 定义一个共用体
    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: %f\n", data.f);
        
        strcpy(data.str, "Hello");
        printf("data.str: %s\n", data.str);
        
        // 访问共用体的成员
        printf("data.i: %d\n", data.i);
        printf("data.f: %f\n", data.f);
        printf("data.str: %s\n", data.str);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    输出

    data.i: 10
    data.f: 3.140000
    data.str: Hello
    data.i: 1819043144
    data.f: 1143139122437582500000000000.000000
    data.str: Hello
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    小端存储 Little Endian

    小端存储(Little Endian)是一种计算机存储数据的方式,
    其中较低有效字节(即数值的最低位字节)存储在较低的内存地址
    较高有效字节存储在较高的内存地址
    在这里插入图片描述

    在小端存储中,多字节数据类型(如整数或浮点数)的字节顺序是从低位到高位。

    例如,对于一个16位整数0x1234,存储在内存中的字节顺序是0x34(低地址)和0x12(高地址)。

    小端存储的特点是:

    1. 较低有效字节存储在较低的内存地址,较高有效字节存储在较高的内存地址。
    2. 对于多字节数据类型,字节的顺序是从低位到高位。
    3. 可以通过简单的指针操作来访问和操作多字节数据类型的各个字节。

    下面是一个示例代码,用于说明C语言中小端存储的特点:

    
    #include 
    
    int main() {
        unsigned int num = 0x12345678;
        unsigned char *ptr = (unsigned char*)#
    
        printf("num: 0x%x\n", num);
        
        printf("Byte order: ");
        for (int i = 0; i < sizeof(num); i++) {
            printf("%02x ", *(ptr + i));
        }
        printf("\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在上述代码中,我们定义了一个无符号整数num,并将其赋值为0x12345678。
    然后,我们使用一个指向num的无符号字符指针ptr。

    通过循环遍历指针ptr,我们打印出num中每个字节的值。
    根据小端存储的特点,输出结果应该是:

    num: 0x12345678
    Byte order: 78 56 34 12

    在这里插入图片描述

    从输出结果可以看出,较低有效字节0x78存储在较低的内存地址,较高有效字节0x12存储在较高的内存地址,符合小端存储的字节顺序。

    unsigned int num = 0x12345678;
    十六进制的一个数字即4bit, 两个数字为8bit = 1Byte
    char类型为1Byte, 即每次可以取出2个数字
    所以是 78 56 34 12

    在实际编程中,我们需要注意小端存储的影响,特别是在处理网络通信、文件IO和数据转换等场景下,需要正确处理字节顺序的转换。

    大端存储与之相反, 这里不做介绍

    共用体与小端存储

    void test() {
        union  {
            short int i;
            char d[2];
        }r, *s=&r;
        s->i = 0x1234;
        printf("%x\n", s->i);  // 1234
        printf("%x, %x\n", s->d[0], s->d[1]);  // 34, 12
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    为什么只能用第一个成员类型的值初始化一个共用体变量

    在C语言中,共用体(union)的所有成员共享同一块内存空间。

    因此,共用体的大小和内存布局是根据它的成员类型来确定的。

    当我们初始化一个共用体变量时,需要指定其中一个成员的值,
    这样编译器才知道如何正确地分配内存和解释这块内存中的内容。

    由于共用体的所有成员共享同一块内存,
    因此使用不同类型的值来初始化共用体变量可能会导致问题。
    如果我们使用非第一个成员类型的值来初始化共用体变量,
    编译器无法准确地确定应该如何解释这块内存中的内容。
    这可能会导致未定义的行为,
    例如访问无效的内存或得到不正确的结果。

    因此,为了确保正确的内存布局和避免未定义的行为,
    C语言规定只能使用第一个成员类型的值来初始化共用体变量。

    第一个成员类型的值来初始化
    第一个成员类型的值来初始化
    第一个成员类型的值来初始化

    这样编译器就能正确地分配内存
    并根据第一个成员类型来解释这块内存中的内容。

    在这里插入图片描述

  • 相关阅读:
    如何让Java项目兼容更多的客户端设备(二)
    PoeAI:免费使用GPT-4的AI聊天机器人平台
    (附源码)小程序+spring boot宠物健康管理系统 毕业设计 201738
    安装 ROS 与mqtt_bridge 指北
    【微服务 Spring Cloud Alibaba】- Nacos 服务注册中心
    以管道的方式来完成复杂的流程处理
    高薪程序员&面试题精讲系列136之你熟悉Dubbo吗?说说Dubbo的底层原理吧
    【LeetCode】895.最大频率栈
    网站备份很重要:WordPress七牛云镜像存储插件,一键镜像静态资源到七牛云
    Frida IOS 堆栈输出与IDA 对应
  • 原文地址:https://blog.csdn.net/qq_44810930/article/details/132664574