typedef struct{ double d_num; char c; int num;}Node;int main(){ Node n = {1.0000, 'a', 3}; printf("%d %c %d\n", n.d_num, n.c, n.num);}
其中应解释为64位double的部分被解释为32位整型。运行以上会显示97 0,怎么用存储结构来解释这种异常?
解决方案
你用的是 32 位系统。我们 gcc -S 看下它的汇编:
1 fld1 2 fstpl 32(%esp) 3 movb $97, 40(%esp) 4 movl $3, 44(%esp) 5 movl 44(%esp), %edx 6 movzbl 40(%esp), %eax 7 movsbl %al, %eax 8 fldl 32(%esp) 9 movl %edx, 16(%esp)10 movl %eax, 12(%esp)11 fstpl 4(%esp)12 movl $.LC1, (%esp)13 call printf14 movl $0, %eax
- 11 行,存入浮点数到地址
4(%esp)
,这是printf
的第一个参数。通过 gdb 可以看到其十六进制表示为0x00000000 0x3ff00000
。把它的前一个字作为一个整数,即「0」; - 10 行,
%eax
的值是把40(%esp)
的低字节(第 6、7 行)弄过来的,即'a'
,也就是打印出来的「97」; - 而
printf
中%c
对应的那个'\0'
是怎么来的呢?它是那个浮点数的后一个字的最低字节。
64 位系统上函数调用方式不一样。结果是 97, \3, 97
。其中第三个「97」是编译器以为那个寄存器 printf
函数不会用所以残留的之前的值,因为它的第二个参数是浮点数,通过 %xmm0
寄存器传递的,但是 printf
认为没有浮点数所以不使用。不同参数所使用的寄存器没什么规律,如下:
The first 6 integer parameters in a function under Linux are passed in registers rdi , rsi, rdx, rex, r8 and r9