Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1296243
  • 博文数量: 436
  • 博客积分: 7854
  • 博客等级: 少将
  • 技术积分: 3225
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-18 16:30
文章分类

全部博文(436)

文章存档

2013年(2)

2012年(56)

2011年(70)

2010年(308)

分类:

2010-06-14 19:52:04

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位覆盖掉了。
阅读(1829) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~