C 为什么应该或不应该';我们不喜欢接受参数的宏而不是执行相同任务的函数吗?

C 为什么应该或不应该';我们不喜欢接受参数的宏而不是执行相同任务的函数吗?,c,function,macros,arguments,c-preprocessor,C,Function,Macros,Arguments,C Preprocessor,下面是两个程序,当半径作为参数传递时,给出圆的面积。但在第一个程序中,macro.c,我将宏用于作业,而在第二个程序中,function.c我将函数用于作业 我熟悉函数的使用及其细微差别。但是接受参数的宏的情况又如何呢?什么时候我们应该更喜欢它们而不是功能?我们什么时候应该避免它们?哪一个性能更好?我知道,如果宏在程序中被多次使用,宏方法将导致大量代码,而对于函数的情况,相同的函数在作业中被多次调用。但除了这个细微的差别,我们还需要注意哪些其他问题 //macro.c #include<

下面是两个程序,当半径作为参数传递时,给出圆的面积。但在第一个程序中,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;
}
//macro.c
#包括
#定义面积(x)(3.14*x*x)
内部主(空)
{
浮点数r1=6.25,r2=2.5,a;
a=面积(r1);
printf(“\n圆的面积=%f”,a);
a=面积(r2);
printf(“\n圆的面积=%f”,a);
}
//功能c
#包括
浮动面积(浮动);
内部主(空)
{
浮点数r1=6.25,r2=2.5;
printf(“\n圆的面积=%f”,面积(r1));
printf(“\n圆的面积=%f”,面积(r2));
}
浮动面积(浮动半径)
{
返回3.14*半径*半径;
}

宏的许多反面:

  • 使用宏时,您将失去所有类型安全设置。传递的参数不会像内联函数那样进行类型检查
  • 由于宏是纯文本替换,它们可能会产生副作用
  • 宏可能会被计算多次并导致错误
因此,最好避免使用
inline
函数

inline
函数确实有自己的反面:

  • 根据see,它们不保证是内联的

但是通过比较,
inline
肯定比宏得分高。

宏将为您提供更好的性能,但仅适用于小代码,而如果您希望函数为您做很多事情,则最好使用函数。 关于这个链接的解释很清楚

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

如果您仍然有任何疑问,我将尝试回答首选函数的一个原因,特别是库代码中的外部函数,是为了在不重新编译使用它们的所有内容的情况下修复错误。例如,修复pi的错误定义…:-)

我唯一认为喜欢宏的时候是在进行泛型编程时,也就是说,您希望相同的代码可以处理各种不同的类型,或者希望以表达式以外的方式使用宏的参数(例如,将运算符作为宏的输入,或字符串化参数等).

再添加一些:)

->在C语言中,宏调用不执行类型检查,甚至不检查参数是否格式正确,而函数调用通常执行

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

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

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

->许多构造很难用宏来表达,或者无法用明显不同的语法来表达

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

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

例如语法:

#定义标识符替换列表

#定义面积(x)(3.14*x*x)

区域(x)为标识符,区域(3.14*x*x)为替换列表

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

在预处理阶段之前:

int main{

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

预处理后:

int main{

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

宏的优势

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

->头顶上的功能降低

宏的缺点

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

->替换列表中的参数未进行类型检查

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

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

_图珀(p++)

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


((p++)>='a'&&(p++)而你的问题从“让我们学点东西”来看似乎是合理的站在立场上,不幸的是,这不是真正的问题,因此堆栈溢出是离题的。使用这两种方法是有原因的,而且现在大多数编译器也支持内联函数。这一点以前已经被问过很多次了:举几个例子:area(++r1);area(r1+r2)@BLUEPIXY这到底意味着什么?这个案例的具体结果是不同的。多重求值失败,智能内联的可能性更大等等,@H2CO3多重求值到底是什么