版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1344521
在C语言中,联合体(union)有点像结构体那样,把不同类型的数据组织起来,但和结构体不大一样,在结构体各成员有各自的内存空间,一个结构体对象的总长度是各成员长度之和。而在联合体中,各成员共享一段内存空间,一个联合体对象的长度等于各成员中最长的长度。
由上面描述可知,联合体应该具备多面性,即在汇编层面上,有时候会显示结构体的特征,或数组特征,或其它基本数据类型特征。
先看一下例子:
1 #include <stdio.h>
2 union xuzhina_dump_c05_s4
3 {
4 int i;
5 char hello[4];
6 };
7
8 int main()
9 {
10 union xuzhina_dump_c05_s4 test;
11 test.i = 0x656463;
12 for ( int i = 0; i < 4; i++ )
13 {
14 printf( "%c", test.hello[i] );
15 }
16
17 printf( "\n" );
18 return 0;
19 }
汇编代码:
(gdb) disassemble main
Dump of assembler code for function main:
0x08048570 <+0>: push %ebp
0x08048571 <+1>: mov %esp,%ebp
0x08048573 <+3>: and $0xfffffff0,%esp
0x08048576 <+6>: sub $0x20,%esp
0x08048579 <+9>: movl $0x656463,0x18(%esp)
0x08048581 <+17>: movl $0x0,0x1c(%esp)
0x08048589 <+25>: jmp 0x80485a8 <main+56>
0x0804858b <+27>: lea 0x18(%esp),%edx
0x0804858f <+31>: mov 0x1c(%esp),%eax
0x08048593 <+35>: add %edx,%eax
0x08048595 <+37>: movzbl (%eax),%eax
0x08048598 <+40>: movsbl %al,%eax
0x0804859b <+43>: mov %eax,(%esp)
0x0804859e <+46>: call 0x8048430 <putchar@plt>
0x080485a3 <+51>: addl $0x1,0x1c(%esp)
0x080485a8 <+56>: cmpl $0x3,0x1c(%esp)
0x080485ad <+61>: setle %al
0x080485b0 <+64>: test %al,%al
0x080485b2 <+66>: jne 0x804858b <main+27>
0x080485b4 <+68>: movl $0xa,(%esp)
0x080485bb <+75>: call 0x8048430 <putchar@plt>
0x080485c0 <+80>: mov $0x0,%eax
0x080485c5 <+85>: jmp 0x80485cf <main+95>
0x080485c7 <+87>: mov %eax,(%esp)
0x080485ca <+90>: call 0x8048460 <_Unwind_Resume@plt>
0x080485cf <+95>: leave
0x080485d0 <+96>: ret
End of assembler dump.
从上面汇编代码来看,unionxuzhina_dump_c05_s4确实以int和char数组进行访问。见下面这两组指令
0x08048579 <+9>: movl $0x656463,0x18(%esp)
0x0804858b <+27>: lea 0x18(%esp),%edx
0x0804858f <+31>: mov 0x1c(%esp),%eax
0x08048593 <+35>: add %edx,%eax
0x08048595 <+37>: movzbl (%eax),%eax
由上面的探讨,union成员类型最好避免是指针类型。因为指针容易被覆盖,会发生“Accessviolation”的错误。假设指针是函数指针,则会出现上一节的coredump。