简体   繁体   English

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

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

First Code:第一个代码:

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

Second Code:第二个代码:

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

Same output to both codes: Area of rectangle is: 50两个代码相同的 output:矩形面积为:50

My Question: So obviously, macros in C language are the same as functions, but macros take less space (fewer lines) than functions.我的问题:很明显,C 语言中的宏与函数相同,但宏比函数占用更少的空间(更少的行)。 Is this the only benefit of using macros instead of functions?这是使用宏而不是函数的唯一好处吗? Because they look roughly the same.因为它们看起来大致相同。

Macros are most definitely not the same as functions.宏绝对不同于函数。 Macros are text substitutions 1 ;宏是文本替换1 ; they are not called like functions.它们不像函数那样被调用

The problem with your AREA macro is that it won't behave well if you pass an expression like AREA(l1+x,l2) - that will expand to (l1+x * l2) , which won't do what you want.你的AREA宏的问题是,如果你传递一个像AREA(l1+x,l2)这样的表达式,它会表现不佳 - 这将扩展为(l1+x * l2) ,它不会做你想要的。 Arguments to macros are not evaluated, they are expanded in place. Arguments 到宏不被评估,它们被扩展到位。

Macros and function-like macros are useful for creating symbolic constants, simplifying repeated blocks of text, and for implementing crude template-like behavior.宏和类似函数的宏对于创建符号常量、简化重复的文本块以及实现粗略的类似模板的行为很有用。


  1. Strictly speaking they are token substitutions, but the principle is the same.严格来说都是token替换,但是原理是一样的。

A case where macros are useful is when you combine them with __FILE__ and __LINE__ .宏很有用的一种情况是当您将它们与__FILE____LINE__结合使用时。

I have a concrete example in the Bismon software project.我在Bismon软件项目中有一个具体的例子。 In its file cmacros_BM.h I define在其文件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__)

and fatal errors are calling something like (example from file user_BM.c )和致命错误正在调用类似(来自文件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);

When that fopen fails, the fatal error message shows the source file and line number of that FATAL_BM macro invocation.fopen失败时,致命错误消息会显示该FATAL_BM宏调用的源文件和行号。

The fatal_stop_at_BM function is defined in file main_BM.c fatal_stop_at_BM function 在文件main_BM.c中定义

Notice also that some of your C files could be generated by programs like GNU bison , GNU m4 , ANTLR , SWIG and that preprocessor symbols are also used by GNU autoconf .另请注意,您的一些 C 文件可能由GNU bisonGNU m4ANTLRSWIG等程序生成,并且GNU autoconf也使用预处理器符号。

Study also the source code of the Linux kernel .还要研究Linux kernel的源代码。 It uses macros extensively.它广泛使用宏。

Most importantly, read the documentation of your C compiler (eg GCC ).最重要的是,阅读 C 编译器的文档(例如GCC )。 Many C compilers can show you the preprocessed form of your C code.许多 C 编译器可以向您显示 C 代码的预处理形式。


Your您的

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

is wrong and should be #define AREA(l, b) ((l) * (b)) if you want AREA(x+2,y-3) to work as expected.是错误的,如果您希望AREA(x+2,y-3)按预期工作,则应为#define AREA(l, b) ((l) * (b))

For performance reasons, you could have defined your function as出于性能原因,您可以将 function 定义为

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

See also:也可以看看:

I agree with @Eric Postpischil.我同意@Eric Postpischil。 Macros are not supported by old compilers and they don't know anything about macros.旧的编译器不支持宏,它们对宏一无所知。 So, this makes debugging harder if you use an old compiler.因此,如果您使用旧的编译器,这会使调试变得更加困难。

Is this the only benefit of using macros instead of functions?这是使用宏而不是函数的唯一好处吗?

No, macros are function-like and can be used to define only very simple things such as simple formulas but it's not recommended to define a C function with them because they try to put everything linear and flat and that's why you may face software design issues and they make debugging harder.不,宏是类似函数的,只能用于定义非常简单的东西,例如简单的公式,但不建议使用它们定义 C function 因为它们试图将所有内容都线性化和平坦化,这就是您可能面临软件设计问题的原因他们使调试更加困难。 So, this is not always a benefit.所以,这并不总是一个好处。

And in your case, I think it's not a big and serious problem.在你的情况下,我认为这不是一个大而严重的问题。

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

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