atoll()函数使用注意事项及分析

atoll是c99标准加入的函数,在编译的时候可能要打开C99标准的编译选项 -std=c99

另外,必须包含stdlib.h头文件,否则会出错。

☞ C程序代码如下所示:

#include <stdio.h>

#include <stdlib.h>  // 声明atoll函数 int main() {     char tempbuf[]="430007020001";     long long unit;

    unit=atoll(tempbuf);     printf("%lld\n", unit);

    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 <stdlib.h>删掉,也就是不声明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位覆盖掉了。

 

☞ 不添加和添加输出结果对比:

    不添加头文件时,输出510290401,显然是错误的;

    添加头文件后,输出430007020001,正确。

posted @ 2017-09-08 11:03  zxiaocheng  阅读(1415)  评论(0编辑  收藏  举报