为什么在使用函数和宏时会得到不同的结果? [英] Why do I get different results when using a function versus a macro?

查看:161
本文介绍了为什么在使用函数和宏时会得到不同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



使用DevCPP IDE,我发现在使用c编程时, pre> float f(float x)
{
return 1 /(1 + x * x);

$ / code>

和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; //步长

s1 = f(a)+ f(b); (i = 1; i <= n-1; i ++)












);

}

s1 =(s1 + 2 * s2)* h / 2;

printf(sum:%f,s1);

getch();
}




输出1:0.693581(使用MACRO)



OUTPUT 2:0.785109(使用函数)


解决方案

这里有很多 可能性。这里有一些。



在函数版本中,参数明确地被输入为 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 ++)

code>

这会导致未定义的行为,因为 X ++ 。这个表达式可以计算任何东西,或者它可以彻底崩溃程序。



最后,函数版本尊重运算符优先级,而宏不。例如,在函数版本中,调用

  f(1  -  1)

会调用 f(0),评估为 1.0f 。在宏版本中,这将扩展为

  1 /(1 + 1  -  1 * 1  -  1)
= 1 /(1 + 1 - 1 - 1)
= 1/0

未定义的行为,因为被零除错误。

避免这种情况的简单方法是不使用宏来定义函数。回到糟糕的旧时代,这是一种标准的做法,但现在C具有 inline 函数和编译器更聪明,您应该更喜欢函数宏。它们更安全,更易于使用,更难以搞砸。它们也是类型感知的,并且不会多次评估参数。



希望这有助于您!


I'm using DevCPP IDE and I found that while programming in c,

Value returned by:

float f(float x)
{
      return 1/(1+x*x);
}

and value returned by f(x) if it's defined as:

#define f(x) 1/(1+x*x)

are different.

Why am I getting different results in these cases?

EDIT:

Here's my code for which I'm getting the anomaly:

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();
}

OUTPUT 1: 0.693581 (using MACRO)

OUTPUT 2: 0.785109 (using function)

解决方案

There are many possibilities here. Here's a few.

In the function version, the argument is explicitly typed as a float. This means that if you call

f(1);

then 1 is converted to the float 1.0f as the argument. Then, when 1 / (1 + x * x) is computed, it evaluates to 1 / 2.0f, which comes out to 0.5f. However, in the macro version, f(1) would be evaluated as 1 / 2 using integer division, yielding the value 0.

Second, in the function version, the argument is evaluated only once. This means that

int x = 0;
f(x++);

will increment x to 1, then pass in the value 0. The result will then be 1.0f. In the macro version, however, the code expands to

1 / (1 + x++ * x++)

This causes has undefined behavior because there is no sequence point between the evaluations of x++. This expression could evaluate to anything, or it could crash the program outright.

Finally, the function version respects operator precedence while the macro does not. For example, in the function version, calling

f(1 - 1)

will call f(0), evaluating to 1.0f. In the macro version, this expands to

  1 / (1 + 1 - 1 * 1 - 1)
= 1 / (1 + 1 - 1 - 1)
= 1 / 0

This causes undefined behavior because of a divide-by-zero error.

The simple way to avoid this is to not use macros to define functions. Way back in the Bad Old Days this was a standard practice, but now that C has inline functions and compilers are way smarter, you should prefer functions to macros. They're safer, easier to use, and harder to mess up. They're also type aware and don't evaluate arguments multiple times.

Hope this helps!

这篇关于为什么在使用函数和宏时会得到不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆