我有一个函数,它为一堆粒子获取速度矩阵,并尝试计算粒子的总动能。
它没有给我正确的价值。为了调试,我在函数中添加了一些printf("value: %e n", energy)
。
现在,返回值取决于我未注释的这些printf
中有多少。
double GetKineticEnergy(int dim, int nParticles, double vel[nParticles][dim], double mass)
{
int i,j;
double sum;
double energy = 0;
for(i=0;i<nParticles;i++) {
sum = 0;
for(j=0;j<dim;j++) {
sum += vel[i][j]*vel[i][j];
}
energy += sum*mass/2;
// printf("energy: %e n", energy);
}
// printf("total: %e n", energy);
return(energy);
}
在返回调用方后,我立即打印返回的值。我得到18.0
、19.0
、21.0
或24.0
,这取决于我取消注释的printf
组合。
我做错了什么?
更新:
在尝试解决此问题时,我已经注释掉了几乎所有内容。该功能简化为
{
double energy = 123;
return(energy);
}
主程序是
int main() {
double a;
double vel[5][5];
a = GetKineticEnergy(1, 1, vel, 1);
printf("value: %e n", a);
}
我得到
value: 0.000000e+00
作为输出。
更新:
如果我对 2D 数组的二维进行硬编码,问题就会消失double vel[][3]
.目前,这似乎是一个有用的修复,但我对这种类型的硬编码感到畏缩。
如果函数位于不同的文件中并且原型不可用GetKineticEnergy
则可能会发生这种情况。请考虑在 main
中声明其原型或包含所需的头文件。
您调用了未定义的行为。
当你面对来自C程序的看似莫名其妙的行为时,它通常是未定义行为的结果。以下是您应该研究的一些潜在问题:
-
编译器警告
默认情况下,编译器通常会省略许多重要的警告消息,您必须自己启用这些消息。由于添加了代码分析,在启用优化的情况下进行编译还可以激活一些额外的警告消息。如果您使用的是 GCC,则至少应该使用
gcc -ansi -pedantic -W -Wall -O2
. -
功能原型
您是否为代码中的所有函数提供了正确的函数声明(带有原型)?如果没有正确的
GetKineticEnergy()
声明,编译器将传递最后一个参数作为int
,并假定返回类型为int
。你
#include <stdio.h>
了吗?printf()
是一个可变参数函数。可变参数函数通常需要与普通函数不同的调用约定。在没有正确原型的情况下调用可变参数函数会导致未定义的行为。 -
缓冲区溢出
您是否为传递给函数的数组分配了足够的内存或指定了足够大的大小?您是否传递了正确的尺寸?访问超出缓冲区限制的元素可能会导致令人困惑的结果,尤其是在启用优化的情况下。