atoll函数使用出现的奇怪问题

frazer 2008-12-05 10:28:48
redhat下,我在程序中使用atoll函数将字符串转为long long int:
char tempbuf[]="430007020001";
long long int unit;
unit=atoll(tempbuf);
当加上atoll的声明,atoll能执行正确;而不加atoll的声明,则执行不正确。
不正确的结果其实就是正确结果的低四个字节对应的整数。

难道有两个atoll实现??

谢谢解答!

...全文
2561 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wyswyg63 2008-12-17
  • 打赏
  • 举报
回复
mark
wyswyg63 2008-12-17
  • 打赏
  • 举报
回复
mark
brookmill 2008-12-17
  • 打赏
  • 举报
回复
谢谢楼主提了个好问题。
其实以前没用过64位返回值,edx:eax就更不懂了
看到这个问题之后临时查的资料,共同学习。
frazer 2008-12-13
  • 打赏
  • 举报
回复
辛苦了,谢谢
brookmill 2008-12-06
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h> // 声明atoll函数
int main()
{
char tempbuf[]="430007020001";
long long int unit;
unit=atoll(tempbuf);
return 0;
}

gcc -S -o test.s test.c
编译器产生的汇编代码是这样的:
        call    atoll  ;调用atoll。返回值的低32位保存在eax,高32位保存在edx
addl $16, %esp ; 调整栈指针,与本题无关
movl %eax, -32(%ebp) ; 把eax里保存的低32位保存到局部变量unit的低32位
movl %edx, -28(%ebp) ; 把edx里保存的高32位保存到局部变量unit的高32位

而如果把#include <stdlib.h>删掉,也就是不声明atoll函数,编译器产生的汇编代码就变成了这样:
        call    atoll
addl $16, %esp
cltd ; AT&T汇编里的cltd指令相当于cdq指令,作用是把eax的32位整数扩展为64位,高32位用eax的符号位填充保存到edx
movl %eax, -32(%ebp)
movl %edx, -28(%ebp)

从汇编代码可以看出:
有atoll声明的时候,编译器知道atoll的返回值是64位,所以直接把edx:eax里面保存的64位返回值赋值给unit
而没有atoll声明的时候,编译器认为atoll的返回值是32位,于是多了一条关键的cltd指令。真正调用atoll的时候,atoll也会把返回值保存在edx:eax;但是main里面不知道,通过cltd指令,用eax的扩展把edx里面保存的有用的高32位覆盖掉了。
icesky_ff 2008-12-05
  • 打赏
  • 举报
回复
不加声明会按编译器自己的理解去做事的
brookmill 2008-12-05
  • 打赏
  • 举报
回复
不加声明的时候,可能编译器会默认的把atoll作为返回int的函数来编译,这样即使等到链接的时候找到了正确的atoll的实现,也是按返回int来处理
星羽 2008-12-05
  • 打赏
  • 举报
回复
等debug进去看看它调用了什么吗
lbh2001 2008-12-05
  • 打赏
  • 举报
回复
atoll是C99标准加入的函数,你要打开C99标准的编译选项

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧