2

以下是两个程序,它们在将半径作为参数传递时给出圆的面积。但是在第一个程序macro.c中,我使用宏来完成这项工作,而在第二个程序function.c中,我正在使用一个函数来完成这项工作。

我熟悉函数的使用,以及它所需要的细微差别。但是接受参数的宏呢?我们什么时候应该更喜欢它们而不是函数?我们什么时候应该避免它们?哪一个提供更好的性能?我知道如果宏在程序中多次使用,宏方法会导致代码庞大,而对于函数的情况,同一个函数会被多次调用。但除了这个微不足道的差异之外,我们还需要注意哪些其他问题?

//macro.c

#include<stdio.h>
#define AREA(x) (3.14*x*x)

int main(void)
{
    float r1=6.25,r2=2.5,a;

    a=AREA(r1);
    printf("\nArea of circle=%f",a);
    a=AREA(r2);
    printf("\nArea of circle=%f",a);
}


//function.c

#include<stdio.h>
float area(float);

int main(void)
{
    float r1=6.25,r2=2.5;
    printf("\nArea of circle=%f",area(r1));
    printf("\nArea of circle=%f",area(r2));
}

float area(float radius)
{
    return 3.14*radius*radius;
}
4

5 回答 5

4

宏的一些反面:

  • 使用宏,您将失去所有类型安全性。传递的参数不像inline函数那样进行类型检查。
  • 由于宏是纯文本替换,它们可能会产生副作用
  • 一个宏可能会被多次评估并导致错误。

所以最好避免它们,inline而是使用函数。

inline函数确实有自己的另一面:

  • 他们不保证是inlined每次看到的。

但考虑到比较,inline绝对得分超过宏。

于 2013-05-08T05:16:05.077 回答
4

更喜欢函数,尤其是库代码中的外部函数的一个原因是,您可以在不重新编译所有使用它们的东西的情况下修复错误。例如,修正你对 pi 的错误定义...... :-)

我唯一能想到更喜欢宏的时候是当你在做泛型编程时,即你希望相同的代码在各种不同的类型上工作,或者你想以除表达式以外的方式使用宏的参数(例如,将运算符作为宏的输入,或对参数进行字符串化等)。

于 2013-05-08T05:19:31.890 回答
1

添加更多:)

-> 在 C 中,宏调用不执行类型检查,甚至不检查参数的格式是否正确,而函数调用通常会这样做。

-> 一个宏不能返回任何不是它内部调用的最后一个表达式的结果的东西。

-> 由于 C 宏仅使用文本替换,这可能会由于重新评估参数和操作顺序而导致意外的副作用和效率低下。

-> 宏中的编译器错误通常很难理解,因为它们指的是扩展代码,而不是程序员键入的代码。

->许多结构很难或不可能使用宏来表达,或者使用明显不同的语法。

于 2013-05-08T05:49:17.060 回答
0

宏会给你更好的性能,但只适用于小代码,而如果你想让你的函数为你做很多事情,那么使用函数会更好。这个链接上的解释很清楚

http://www.c4learn.com/difference-between-macro-and-function-in-c-programming.html

如果您还有任何疑问,我会尽力回答

于 2013-05-08T05:18:58.420 回答
0

#define 指令指定宏标识符和替换列表。

重新定义先前定义的宏是不合法的,除非新定义与旧定义完全相同。

例如语法:

#define 标识符替换列表

#define 面积(x)(3.14*x*x)

AREA(x) 是标识符 anf (3.14*x*x) 是替换列表

替换在预处理时完成 在预处理阶段结束时,替换完成。

在预处理阶段之前:

诠释主要{

      float r1=6.25,r2=2.5,a;
      a=AREA(r1);
      printf("\nArea of circle=%f",a);
      a=AREA(r2);
      printf("\nArea of circle=%f",a);
      return 0;

}

预处理后:

诠释主要{

      float r1=6.25, r2=2.5,a;
      a=(3.14*r1*r1);
      printf("\nArea of circle=%f",a);
      a=AREA(3.14*r2*r2);
      printf("\nArea of circle=%f",a);
      return 0;

}

宏的优点

-> 当替换列表中的代码较小时,我们可以使用 MACROS。因为替换是在预处理期间完成的,所以程序不必在运行期间在函数之间切换控件。并且程序执行速度非常快。

-> 函数开销减少。

MACROS的缺点

->程序员的最终目标是编写更小的程序。替换列表中的代码更多时,会发生什么!出现代码冗余,从优秀程序员的角度来看,这是非常糟糕的。这就是功能发挥作用的地方。

->替换列表中的参数没有经过类型检查。

-> 指定使用递增 (++)、递减 (- -) 和赋值运算符(例如 +=)的宏参数不是一个好的编程习惯

例如,不要将以下参数传递给 _toupper 宏:

_toupper(p++)

当在宏定义中替换参数 p++ 时,程序流内的效果如下:

((p++) >= 'a' && (p++) <= 'z' ? (p++) & 0X5F : (p++))

由于 p 正在递增,因此在此宏替换中每次出现的值都不相同。即使您知道可能的副作用,宏定义中的替换列表也可以更改,这会在没有警告的情况下更改副作用。

所以,一切都有其优点和缺点:)

于 2013-05-08T06:14:53.417 回答