我正在使用带有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,但最后一个也被破坏了。我花了好几个小时试图发现错误。
有什么建议吗?
答案 0 :(得分:1)
main()
中所有变量的类型是否都指定为float
?dotprod()
的原型是否可见?换句话说,您的主文件是否有#include "myfuns.h"
?特别是,对第二个问题回答“否”意味着编译器会对传递的参数做出某些假设,这些假设会使值变为不同的宽度,或者以不同的方式解释它们。
例如,考虑:
#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)。
在这种特殊情况下,我的int
和float
类型具有相同的宽度(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 );