首页 > 开发 > C++ > 正文

C/C++ 中结构体输出异常的原因(存储结构)

2017-09-11 21:35:26  来源: 网友分享
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