簡體   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