繁体   English   中英

在 C 中使用宏而不是函数有什么好处?

[英]What are the benefits of using macros instead of functions in C?

第一个代码:

#include <stdio.h>
 
int area(int a,int b){
        int area1 = a*b;
        return area1;
    }
int main()
{
    
    int l1 = 10, l2 = 5, area2;
 
    area2 = area(l1,l2);
 
    printf("Area of rectangle is: %d", area2);
 
    return 0;
}

第二个代码:

#include <stdio.h>
 
// macro with parameter
#define AREA(l, b) (l * b)

int main()
{
    int l1 = 10, l2 = 5, area;
 
    area = AREA(l1, l2);
 
    printf("Area of rectangle is: %d", area);
 
    return 0;
}

两个代码相同的 output:矩形面积为:50

我的问题:很明显,C 语言中的宏与函数相同,但宏比函数占用更少的空间(更少的行)。 这是使用宏而不是函数的唯一好处吗? 因为它们看起来大致相同。

宏绝对不同于函数。 宏是文本替换1 ; 它们不像函数那样被调用

你的AREA宏的问题是,如果你传递一个像AREA(l1+x,l2)这样的表达式,它会表现不佳 - 这将扩展为(l1+x * l2) ,它不会做你想要的。 Arguments 到宏不被评估,它们被扩展到位。

宏和类似函数的宏对于创建符号常量、简化重复的文本块以及实现粗略的类似模板的行为很有用。


  1. 严格来说都是token替换,但是原理是一样的。

宏很有用的一种情况是当您将它们与__FILE____LINE__结合使用时。

我在Bismon软件项目中有一个具体的例子。 在其文件cmacros_BM.h我定义

// only used by FATAL_BM macro
extern void fatal_stop_at_BM (const char *, int) __attribute__((noreturn));
#define FATAL_AT_BIS_BM(Fil,Lin,Fmt,...) do {                   \
    fprintf(stderr, "BM FATAL:%s:%d: <%s>\n " Fmt "\n\n",       \
            Fil, Lin, __func__, ##__VA_ARGS__);                 \
    fatal_stop_at_BM(Fil,Lin); } while(0)

#define FATAL_AT_BM(Fil,Lin,Fmt,...) FATAL_AT_BIS_BM(Fil,Lin,Fmt,##__VA_ARGS__)

#define FATAL_BM(Fmt,...) FATAL_AT_BM(__FILE__,__LINE__,Fmt,##__VA_ARGS__)

和致命错误正在调用类似(来自文件user_BM.c的示例)

  FILE *fil = fopen (contributors_filepath_BM, "r+");
  if (!fil)
    FATAL_BM ("find_contributor_BM cannot open contributors file %s  : %m",
              contributors_filepath_BM);

fopen失败时,致命错误消息会显示该FATAL_BM宏调用的源文件和行号。

fatal_stop_at_BM function 在文件main_BM.c中定义

另请注意,您的一些 C 文件可能由GNU bisonGNU m4ANTLRSWIG等程序生成,并且GNU autoconf也使用预处理器符号。

还要研究Linux kernel的源代码。 它广泛使用宏。

最重要的是,阅读 C 编译器的文档(例如GCC )。 许多 C 编译器可以向您显示 C 代码的预处理形式。


您的

 // macro with parameter
 #define AREA(l, b) (l * b)

是错误的,如果您希望AREA(x+2,y-3)按预期工作,则应为#define AREA(l, b) ((l) * (b))

出于性能原因,您可以将 function 定义为

inline int area(int a,int b){ return a*b; }

也可以看看:

我同意@Eric Postpischil。 旧的编译器不支持宏,它们对宏一无所知。 因此,如果您使用旧的编译器,这会使调试变得更加困难。

这是使用宏而不是函数的唯一好处吗?

不,宏是类似函数的,只能用于定义非常简单的东西,例如简单的公式,但不建议使用它们定义 C function 因为它们试图将所有内容都线性化和平坦化,这就是您可能面临软件设计问题的原因他们使调试更加困难。 所以,这并不总是一个好处。

在你的情况下,我认为这不是一个大而严重的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM