文章目录
- 共用体解释
- 代码说明
- 小端存储 Little Endian
- 共用体与小端存储
- 为什么只能用第一个成员类型的值初始化一个共用体变量
共用体解释
共用体(Union
)是一种特殊的数据类型,
它允许在同一个内存位置存储不同的数据类型。
共用体的所有成员共享同一块内存空间,
因此同一时间只能存储其中一个成员的值。
共用体的定义和结构体类似,使用关键字union
,后面跟着成员列表。
每个成员可以是不同的数据类型,
但共用体的所有成员都共享同一块内存空间,大小取决于最大的成员。
共用体的成员可以通过点操作符(.)或箭头操作符(->)来访问。
共用体的主要特点如下:
- 共用体的大小取决于最大的成员的大小。
- 共用体的成员共享同一块内存空间,只能同时存储其中一个成员的值。
- 对共用体的任何成员的修改都会影响到其他成员。
- 共用体的成员可以具有不同的数据类型,但它们在内存中的起始位置是相同的。
共用体的主要用途有:
- 节省内存空间:当多个成员变量不会同时使用,但需要共享同一块内存空间时,可以使用共用体来节省内存。
- 数据类型转换:共用体可以用于不同类型之间的转换,通过存储一个成员变量,然后通过另一个成员变量来读取转换后的值。
需要注意的是,由于共用体的成员共享同一块内存空间,因此在使用共用体时需要谨慎处理成员的赋值和读取操作,以免出现意外的结果。
代码说明
#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(高地址)。
小端存储的特点是:
- 较低有效字节存储在较低的内存地址,较高有效字节存储在较高的内存地址。
- 对于多字节数据类型,字节的顺序是从低位到高位。
- 可以通过简单的指针操作来访问和操作多字节数据类型的各个字节。
下面是一个示例代码,用于说明C语言中小端存储的特点:
#include <stdio.h>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;
}
在上述代码中,我们定义了一个无符号整数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语言规定只能使用第一个成员类型的值来初始化共用体变量。
第一个成员类型的值来初始化
第一个成员类型的值来初始化
第一个成员类型的值来初始化
这样编译器就能正确地分配内存
,
并根据第一个成员类型来解释这块内存中的内容。