为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕码人8056858 2019-04-08 11:17:02
typedefstruct{doubled_num;charc;intnum;}Node;intmain(){Noden={1.0000,'a',3};printf("%d%c%d\n",n.d_num,n.c,n.num);}其中应解释为64位double的部分被解释为32位整型。运行以上会显示970,怎么用存储结构来解释这种异常?
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

你用的是32位系统。我们gcc-S看下它的汇编:
1fld1
2fstpl32(%esp)
3movb$97,40(%esp)
4movl$3,44(%esp)
5movl44(%esp),%edx
6movzbl40(%esp),%eax
7movsbl%al,%eax
8fldl32(%esp)
9movl%edx,16(%esp)
10movl%eax,12(%esp)
11fstpl4(%esp)
12movl$.LC1,(%esp)
13callprintf
14movl$0,%eax
11行,存入浮点数到地址4(%esp),这是printf的第一个参数。通过gdb可以看到其十六进制表示为0x000000000x3ff00000。把它的前一个字作为一个整数,即「0」;
10行,%eax的值是把40(%esp)的低字节(第6、7行)弄过来的,即'a',也就是打印出来的「97」;
而printf中%c对应的那个'\0'是怎么来的呢?它是那个浮点数的后一个字的最低字节。
64位系统上函数调用方式不一样。结果是97,\3,97。其中第三个「97」是编译器以为那个寄存器printf函数不会用所以残留的之前的值,因为它的第二个参数是浮点数,通过%xmm0寄存器传递的,但是printf认为没有浮点数所以不使用。不同参数所使用的寄存器没什么规律,如下:
Thefirst6integerparametersinafunctionunderLinuxarepassed
inregistersrdi,rsi,rdx,rex,r8andr9
                            
查看完整回答
反对 回复 2019-04-08
?
喵喔喔

TA贡献1735条经验 获得超5个赞

printf("%d%c%d\n",n.d_num,n.c,n.num);
首先观察应该更加细致一点,应该还有更多的东西你需要测试。
printf("%d\n%c\n%d\n",n.d_num,n.c,n.num);
下面进入正题:
首先我们看一下正常的情况,%lf%c%d,printf()函数是怎么运行的呢?它从右到做把%lf%c%d压到栈里面去,然后就去结构体中取数据了[2]。现在栈顶是%lf,那么取64位出来,就得到了d.d_num,然后取8位的d.c,最后取32位的d.num。(我这里没有考虑内存对齐的问题和各种细节)
然后我们来看%d%c%d,他取数据大小的顺序则是32832,ok,那么堆栈里的数据是
1.0000,'a',3
show_double(n.d_num);
show_char(n.c);
show_int(n.num);
//n.d_num:0x000000000000f03f
//n.c:0x61
//n.num:0x03000000
我们看一下,32位全为0,后面连续的8位也为0,manascii'\0'=>0,
剩下的显示的n.num就是32位的0x61了,也就是a,至于最后的n.num,压根没动。
尝试把1.000改大一点,结果自然会变化。
参考:
csappshow_bytescode
stackoverflow:HowdoestheparticularCfunctionwork?
                            
查看完整回答
反对 回复 2019-04-08
  • 2 回答
  • 0 关注
  • 387 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信