nxdong July 30, 2022 [cpp ] #cpp
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/ ) 在线观察汇编对应情况
参考资料
https://en.wikipedia.org/wiki/Sizeof