使用函数与宏时,为什么会得到不同的结果?
我正在使用DevCPP IDE,我发现在用c编程时,
返回的值:
float f(float x) { return 1/(1+x*x); }
和f(x)返回的值如果定义为:
#define f(x) 1/(1+x*x)
是不同的。
为什么我在这些情况下会得到不同的结果?
编辑:
这是我的代码,我得到了exception:
main() { int i; float a=0, b=1, h, n=12, s1, s2=0; h=(ba)/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)
输出2:0.785109(使用function)
这里有很多种可能性。 这里有几个。
在函数版本中,参数显式地键入为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
函数和编译器更聪明,你应该更喜欢函数到宏。 它们更安全,更易于使用,更难以搞定。 它们也是类型感知的,并且不会多次评估参数。
希望这可以帮助!
#define f(x) 1/(1+x*x)
应定义为
#define f(x) 1/(1+(x)*(x))
试试这个:
#define f(x) (1/(1+x*x))
#define
基本上将代码放在#define
‘名称所在的位置,因此将应用操作顺序和优先顺序。