文章目录

    • 共用体解释
    • 代码说明
    • 小端存储 Little Endian
    • 共用体与小端存储
    • 为什么只能用第一个成员类型的值初始化一个共用体变量

共用体解释

共用体(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;}

输出

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

小端存储 Little Endian

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

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

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

小端存储的特点是:

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

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

#include 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);// 1234printf("%x, %x\n", s->d[0], s->d[1]);// 34, 12}

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

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

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

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

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

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

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

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