我正在使用DevCPP IDE,我发现用c编程时,
返回的值:
float f(float x)
{
return 1/(1+x*x);
}
和f(x)返回的值,如果它被定义为:
#define f(x) 1/(1+x*x)
是不同的。
为什么我在这些情况下会得到不同的结果?
编辑:
这是我的代码,我得到了异常:
main()
{
int i;
float a=0, b=1, h, n=12, s1, s2=0;
h=(b-a)/n; //step length
s1=f(a)+f(b);
for(i=1;i<=n-1;i++)
{
s2+=f(a+(i*h));
}
s1=(s1+2*s2)*h/2;
printf("sum: %f", s1);
getch();
}
输出1:0.693581(使用MACRO)
OUTPUT 2:0.785109(使用功能)
答案 0 :(得分:3)
这里有许多的可能性。这里有几个。
在函数版本中,参数显式地输入为float
。这意味着如果你打电话
f(1);
然后将1
转换为float 1.0f
作为参数。然后,当计算1 / (1 + x * x)
时,它的计算结果为1 / 2.0f
,它出现在0.5f
。但是,在宏版本中,f(1)
将使用整数除法计算为1 / 2
,从而产生值0.
其次,在函数版本中,参数仅计算一次。这意味着
int x = 0;
f(x++);
会将x
增加到1
,然后传入值0
。结果将是1.0f
。但是,在宏版本中,代码会扩展为
1 / (1 + x++ * x++)
这会导致未定义的行为,因为x++
的评估之间没有序列点。该表达式可以评估为任何,或者它可能会直接使程序崩溃。
最后,函数版本遵循运算符优先级,而宏则不支持。例如,在函数版本中,调用
f(1 - 1)
将致电f(0)
,评估为1.0f
。在宏版本中,这将扩展为
1 / (1 + 1 - 1 * 1 - 1)
= 1 / (1 + 1 - 1 - 1)
= 1 / 0
由于零除错误,这会导致未定义的行为。
避免这种情况的简单方法是不使用宏来定义函数。回到Bad Old Days这是一个标准的做法,但是现在C有inline
函数和编译器更聪明,你应该更喜欢函数到宏。它们更安全,更易于使用,更难搞乱。它们也是类型识别的,不会多次评估参数。
希望这有帮助!
答案 1 :(得分:1)
#define f(x) 1/(1+x*x)
应定义为
#define f(x) 1/(1+(x)*(x))
答案 2 :(得分:0)
试试这个:
#define f(x) (1/(1+x*x))
#define
基本上将代码粘贴到#define
'名称所在的位置,因此操作和优先顺序将适用。