函数的返回值,16位/32位

原创 2004年06月27日 15:44:00

同事的一段代码里出现的异常,内存访问错误。遂一起排查。使用的是VC6.0,系统是Win2K。

主调函数func1,传进一个数组的首地址。用数组的下标方式访问,下标是一个子函数func2的返回值。异常出现在这里。一开始怀疑传进来的地址有问题,跟踪下来发现是对的。我怀疑func2的返回值,但看到这个函数很简单,就一句返回一个结构的WORD成员,好象不应该有错。

func2有一个参数,是一个结构指针lp,函数体是return lp->val。函数声明返回WORD类型,结构的成员val也是WORD类型。

在出事地前加了个printf("%x/n",func2(p)),打印func2的返回值。结果说明了出错原因,打印值是1520000。很明显,func2返回了一个DWORD值。访问数组越界,所以异常。

为什么会这样呢?为什么函数返回类型是WORD,使用时却得到一个DWORD值呢?

做了一个尝试,如果把返回值赋给一个WORD类型的局部变量,得到的值是对的;如果加上类型转换(WORD)func2(p)也是对的。

分别看一下这三种情况(一错二对)的汇编码,可以发现,正确的情况,在func1中使用func2的返回值前有一句:

0040B7F2   and         eax,0FFFFh   //清高16位。

因为在调用func2时,结构指针参数的传递用了32位的eax。func2的汇编码中可以看到,需返回的WORD值放入了16位的ax。所以在func1使用前清高16位,使用的仍然是eax,但值是所需的正确值。

而错误的情况,即不加转换的直接使用,没有这么一句清高位。赋值的时候也没有使用movzx零扩展指令,直接用mov到eax。

0040B7E6   mov         edx,dword ptr [ebp-4]
0040B7E9   push        edx
0040B7EA   call        @ILT+5(_func) (0040100a)
0040B7EF   add         esp,4
0040B7F2   and         eax,0FFFFh     //出错的代码没这句。
0040B7F7   push        eax
0040B7F8   push        offset string "a = %d/n" (00420f74)
0040B7FD   call        printf (00401090)
0040B802   add         esp,8

怀疑是编译器的bug。于是做一个实验。新建一个project,模拟了这个func1和func2。结果的正确的。即使是不加转换的直接使用汇编码里也有清高位,返回的值不会受干扰。更加疑惑。

继续实验。怀疑实际的那个结构有问题。把实际project中的结构移植到实验project中。却也是正确的。

怀疑project的设置有问题。把实验中的结构和函数移植到实际project中,又是正确的。郁闷。

改变此成员在结构中的定义位置,怀疑没有对齐,虽然这不应该是程序员关心的,但也没有发现区别。改变此成员的类型(DWORD,BYTE),都没有找出问题所在。至此,技穷。

希望能找到问题的根源。

c语言,c++函数返回一个数组,二维数组

与其他高级语言相比,c语言,c++ 最大的不方便之处就是 函数只能返回一个数值。若要返回一个数组,必须用到指针以及动态分配内存。 这是一个坎,就如学吉他时的大横按一样,不少人在这个坎上望而却步。 我前...
  • robert_chen1988
  • robert_chen1988
  • 2016年12月10日 00:34
  • 5531

MD5加密与byte[]数组与十六进制字符串与字符串的互相转换

概括为三种方式: 方式一:Integer.toHexString(int)   对应的是: Integer.parseInt(String, int)或者Integer.valueOf(String...
  • DennisRuan
  • DennisRuan
  • 2016年04月15日 11:56
  • 2659

为什么C语言里不推荐强制转换malloc的返回值?

在C里,用malloc动态分配内存时,是不推荐强转其返回值的。例如 int *arr = malloc(sizeof(int) * 5); 而不是 int *arr = (int *)mal...
  • bestone0213
  • bestone0213
  • 2014年11月05日 19:54
  • 1497

LJH_决定C++语言中函数的返回值类型

  • 2017年09月22日 08:53
  • 3.48MB
  • 下载

Swift视频教程:函数篇 形式参数与返回值①多参和无参

  • 2015年08月26日 16:25
  • 24.83MB
  • 下载

C++函数调用传参与返回值深度分析

  • 2012年02月16日 22:48
  • 4KB
  • 下载

Swift视频教程:函数篇 形式参数与返回值④可选元组返回

  • 2015年08月26日 16:30
  • 43.69MB
  • 下载

printf函数返回值

  • 2015年08月26日 10:39
  • 95B
  • 下载

函数的返回值(微软).

  • 2012年11月17日 23:58
  • 173KB
  • 下载

关于函数返回值的讨论

  • 2012年08月29日 14:46
  • 219KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:函数的返回值,16位/32位
举报原因:
原因补充:

(最多只允许输入30个字)