C union 关键字
C union 关键字的一些用法
基本原则
- union中可以定义多个成员,union的大小由最大的成员的大小决定。
- union成员共享同一块大小的内存,一次只能使用其中的一个成员。
- 对某一个成员赋值,会覆盖其他成员的值
- 联合体union的存放顺序是所有成员都从低地址开始存放的。
代码
union.c 文件如下:
#include <stdio.h>
#include <string.h>
typedef union
{
char str[100];
char c;
int i;
float f;
} MyUnion;
void print_union(MyUnion *u)
{
printf("MyUnion size: %d c:%c i:%d f:%f str:%s\n", sizeof(*u), u->c, u->i, u->f, u->str);
}
int main(int argc, char **argv)
{
MyUnion d;
d.c = 'H';
print_union(&d);
d.i = 49;
print_union(&d);
d.f = 3.14;
print_union(&d);
strcpy(d.str, "Hello world!");
print_union(&d);
printf("MyUnion Size : %d \n", sizeof(MyUnion));
printf("sizeof MyUnion : %d \n", sizeof((MyUnion){{0}}));
printf("sizeof MyUnion.str : %d \n", sizeof((MyUnion){{0}}).str);
printf("sizeof MyUnion.c : %d \n", sizeof((MyUnion){{0}}).c);
printf("sizeof MyUnion.i : %d \n", sizeof((MyUnion){{0}}).i);
printf("sizeof MyUnion.f : %d \n", sizeof((MyUnion){{0}}).f);
return 0;
}
编译运行
gcc union.c
MyUnion size: 100 c:H i:72 f:0.000000 str:H
MyUnion size: 100 c:1 i:49 f:0.000000 str:1
MyUnion size: 100 c:� i:1078523331 f:3.140000 str:��H@
MyUnion size: 100 c:H i:1819043144 f:1143139122437582505939828736.000000 str:Hello world!
MyUnion Size : 100
sizeof MyUnion : 100
sizeof MyUnion.str : 100
sizeof MyUnion.c : 1
sizeof MyUnion.i : 4
sizeof MyUnion.f : 4
附注
sizeof((MyUnion){{0}}).f 的操作会不会有性能损失?
不会。sizeof 是编译期间求值的。
The operator sizeof produces the required memory storage space of its operand when the code is compiled
参考: https://en.wikipedia.org/wiki/Sizeof
union2.c 如下
#include <stdio.h>
#include <string.h>
typedef union
{
int f;
} MyUnion;
int main(int argc, char **argv)
{
MyUnion d;
d.f = 3;
int a = sizeof d;
int b = sizeof d.f;
int c = sizeof((MyUnion){0}).f;
return 0;
}
编译对应的汇编代码:
gcc -S -masm=intel union2.c -o union2.s
union2.s的内容如下:
.file "union2.c"
.intel_syntax noprefix
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
mov DWORD PTR -20[rbp], edi
mov QWORD PTR -32[rbp], rsi
mov DWORD PTR -16[rbp], 3
mov DWORD PTR -12[rbp], 4
mov DWORD PTR -8[rbp], 4
mov DWORD PTR -4[rbp], 4
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 11.1.0"
.section .note.GNU-stack,"",@progbits
可以观察到汇编代码中是常量。
也可以通过[godbolt](https://godbolt.org/) 在线观察汇编对应情况
