C语言共用体详解

共用体解释

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

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

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

共用体的主要特点如下:

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

共用体的主要用途有:

  1. 节省内存空间:当多个成员变量不会同时使用,但需要共享同一块内存空间时,可以使用共用体来节省内存。
  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: %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;
}

输出

data.i: 10
data.f: 3.140000
data.str: Hello
data.i: 1819043144
data.f: 1143139122437582500000000000.000000
data.str: Hello

小端存储 Little Endian

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

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

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

小端存储的特点是:

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

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


#include <stdio.h>

int main() {
    unsigned int num = 0x12345678;
    unsigned char *ptr = (unsigned char*)&num;

    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;
}

在上述代码中,我们定义了一个无符号整数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
}

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

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

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

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

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

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

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

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

在这里插入图片描述

  • 32
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值