redhat下,我在程序中使用atoll函数将字符串转为long long int:
char tempbuf[]="430007020001";
long long int unit;
unit=atoll(tempbuf);
当加上atoll的声明,atoll能执行正确;而不加atoll的声明,则执行不正确。
不正确的结果其实就是正确结果的低四个字节对应的整数。
难道有两个atoll实现??
-----------------------
1.atoll是C99标准加入的函数,你要打开C99标准的编译选项
2.不加声明的时候,可能编译器会默认的把atoll作为返回int的函数来编译,这样即使等到链接的时候找到了正
确的atoll的实现,也是按返回int来处理
3.不加声明会按编译器自己的理解去做事的
4.
C/C++ code
#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
编译器产生的汇编代码是这样的:
- Assembly code
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 删掉,也就是不声明atoll函数,编译器产生的汇编代码就变成了这样:
- Assembly code
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位覆盖掉了。
阅读(1886) | 评论(0) | 转发(0) |