C函数调用参数被扰乱

时间:2012-10-09 06:18:27

标签: c++ function

我正在使用带有gcc的Netbeans,我发现函数参数的值在调用函数和被调用函数之间被破坏。

在myfuns.h中:

float dotprod( float u1, float u2, float u3,  float v1, float v2, float v3 );

在myfuns.c中

 float dotprod( float u1, float u2, float u3, float v1, float v2, float v3 )
 {
    float res= u1*v1+u2*v2+u3*v3 ;
    return res;
 }

在main.c中

 ...
 float dp=dotprod( rx, ry, rz,  ddx, ddy, ddz );
 ...

如果我在dotprod()函数中打印u1,u2等的值,或者用它来检查它们 调试器,值与main.c中的rx,ry等值不同

如果我将参数从float转换为float *,问题似乎就消失了。我也 尝试在6个浮点参数之前和之后添加一个虚拟整数参数,第一个是OK,但最后一个也被破坏了。我花了好几个小时试图发现错误。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

  1. main()中所有变量的类型是否都指定为float
  2. 调用时,dotprod()的原型是否可见?换句话说,您的主文件是否有#include "myfuns.h"
  3. 特别是,对第二个问题回答“否”意味着编译器会对传递的参数做出某些假设,这些假设会使值变为不同的宽度,或者以不同的方式解释它们。

    例如,考虑:

    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        float x = 1.5, y = 2.5;
        fn (x, y);                       // <-- compiler makes assumptions.
        return 0;
    }
    
    void fn (float a, float b) {         // <-- compiler should complain
        printf ("%f %f\n", a, b);        //     about bad assumptions.
    }
    

    输出:

    0.000000 1.937500
    

    那真的你会期待什么。这是用gcc编译的,一连串的警告应该是有理由返回并检查代码(a)

    在这种特殊情况下,我的intfloat类型具有相同的宽度(32位)但是,因为编译器认为函数接受int,它会将这些浮点数转换为那种类型首先。不幸的是,当函数查看堆栈上的那些int值时,它会将它们解释为float类型,这些类型的编码方式完全不同。

    如果您的预期和实际类型的宽度不同,可能会更糟,因为您可能会发现尝试使用的数据多于堆栈中的数据。

    只需插入以下内容即可修复此特定代码示例:

    void fn (float, float);
    

    之前main()(或交换main()fn()),以便不假设原型。这导致gcc没有警告和正确的输出:

    1.500000 2.500000
    

    基本上,您必须确保调用者和被调用者同意传递的参数。其中包括调用约定,数据类型和参数计数等。 任何中的不匹配都会导致您遇到问题。


    (a):如下所示,在我的系统上:

    testprog.c: In function ‘main’:
    testprog.c:5: warning: implicit declaration of function ‘fn’
    testprog.c: At top level:
    testprog.c:9: warning: conflicting types for ‘fn’
    testprog.c:5: note: previous implicit declaration of ‘fn’ was here
    

答案 1 :(得分:0)

确保使用函数参数传递相同的类型的数据,即大小和表示。

对于一个非常简单的测试,请在main中尝试:

float dp=dotprod( (float)rx, (float)ry, (float)rz,  (float)ddx, (float)ddy, (float)ddz );