簡體   English   中英

C多行宏問題:為什么不在多行宏定義中使用if(1){...}而不是do {...} while(0)

[英]C multi-line macro issue: why not use if(1){…} instead of do{…}while(0) in multi-line macro definition

我想調用循環中的多行宏來打破/繼續它。

如果我在多行宏定義中使用“do {...} while(0)”,則break / continue僅對“do {...} while(0)”有效,而不是調用此宏的循環。 所以我考慮在多宏定義中使用“if(1){...}”。

#define EXIT_CIRCULATION() \
        if(1){ \
           break; \
        }

void func(){
    while(1){
       ...
       EXIT_CIRCULATION();
       ...
    }
}

但我懷疑在宏定義中使用“if(1){...}”是一種好方法,因為我在互聯網上找不到任何例子。

謝謝!

如果您編寫類似的東西

 if (somecondition)
    EXIT_CIRCULATION();
 else
    break;

那么你的宏的擴展將不會像你直覺所期望的那樣。 else將適用於你的if (1)並且永遠不會發生。

這個技巧背后的整個想法是找到一種方法來創建一個多行(即復合)語句,該語句也包含一個終止; 作為其組成部分。 這將給你機會使用; 在宏調用之后,不會無意中引入空語句。

{ ... }中的普通復合語句不起作用,因為它沒有結束; C / C ++中唯一以...結尾的多行語句; do/while C / C ++語法中沒有其他語句可以滿足此要求。 (這是一個不准確的聲明,請參閱下面的“PS”)

在所有其他情況下(包括你的if (1) {...}; 宏調用之后將被視為另一個獨立的獨立空語句。 這樣就不可能寫出一個; 在宏調用之后,當它在需要完全一個語句的上下文中使用時(如if-else真分支或do/while循環的主體)。

例如,如果您定義

#define A() if (1) {}

那么這段代碼將無法編譯

do
  A();
while (1);

因為它將被取代

do
  if (1) {}; /* <- two statements, not one */
while (1);

這實際上是dowhile之間的兩個陳述。 dowhile之間指定兩個語句而不將它們包裝到{}是語法錯誤。

PS更正:我上面提到的關於do/while 唯一可行的變體的說法是不正確的。 在@Michael Burr的回答中,你可以看到另一個合適的變體,它使用else ((void) 0)技巧用於相同的目的。 但是,主要原則仍然是相同的。

這是一個我認為可以安全地做你想要的宏:

#define EXIT_CIRCULATION()  \
            if (1) {        \
                /* some statements */   \
                break;                  \
            }                           \
            else                        \
                do {} while (0)

if這里與else匹配的事實意味着宏可以安全地在另一個內部使用if ,並且因為else子句是do-nothing do / while語句,它提供了類似的屬性來包裝多行宏一個do / while 例如,宏需要用分號終止,就像它是正常的聲明一樣; 忘記分號將導致語法錯誤。 它在另一個ifelse子句中扮演的很好。

最重要的是對你(我認為), break語句不會被宏吞沒 - 它將打破宏所用的循環。

這是否是一個好主意完全是另一回事。 許多程序員不喜歡將流控制語句隱藏在宏中(除非控制流完全在宏單元內)。

這是在行動:

#include<stdio.h>
#include<stdlib.h>

#define EXIT_CIRCULATION()  \
            if (1) {        \
                puts("done.");          \
                break;                  \
            }                           \
            else                        \
                do {} while (0)

int main()
{
    int i = 0;

    for (i = 0; i < 10; ++i) {
        if (i  > 4)
            EXIT_CIRCULATION();
        else
            puts("working...");
    }

    printf("i == %d\n", i);

    return 0;
}

輸出:

working...
working...
working...
working...
working...
done.
i == 5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM