簡體   English   中英

C中宏的意外行為

[英]Unexpected behaviour of macros in C

以下兩個代碼如何執行(除了第二行中的分號,其他代碼相同)

該代碼有望執行,並且也會執行。

#include<stdio.h>
#define SWAP(a, b) int t; t=a, a=b, b=t  //note here is no semi-colon at the end
int main()
{
    int a=10, b=12;
    SWAP(a, b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

但是,由於SWAP(a, b)將被int t; t=a, a=b, b=t;;代替,因此以下命令不會運行int t; t=a, a=b, b=t;; int t; t=a, a=b, b=t;; 因此,兩個分號會產生錯誤!!!

#include<stdio.h>
#define SWAP(a, b) int t; t=a, a=b, b=t;  //note the semi-colon here
int main()
{
    int a=10, b=12;
    SWAP(a, b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

流浪分號成為空語句,這在C語言中是完全合法的。

您可以通過在代碼中添加包含十幾個分號的行來證明這一點。

另外,您的宏最好寫成:

#define SWAP(a, b) do { int t = a; a = b; b = t; } while (0)

如果您嘗試在單個代碼塊中進行兩次不同的交換,則效果更好。

如果在宏中使用,局部范圍內的多余分號將永遠不會在C中產生錯誤(C99之后)。 他們只是引入了一個空語句。 您從哪里得知應該是一個錯誤? 人們可以編造會觸發,比方說,一個“孤立別人”的錯誤,因為多余的分號的例子,但宏無法使用下if反正(見下文)。

在C89 / 90中,可以通過在聲明后無意間放置多余的分號來觸發錯誤,因為在C89 / 90中,混合使用聲明和語句是非法的。 例如

int a, b;;  /* <- A declaration followed by an empty statement */
int c;      /* <- ERROR: Illegal declaration after a statement */

但是在C99中,這不是問題,因為聲明和語句可以混合使用。 您的SWAP顯然是針對C99實施的,因此此問題不會立即適用。

值得注意的是, SWAP這種實現非常差且非常危險。 在以下情況下,它可能導致意外,危險和完全無意義的行為

if (/* whatever */)
  SWAP(a, b);

最好遵循do/while(0)習慣用法,然后執行類似

#define SWAP(a, b) do { int t; t=a, a=b, b=t; } while (0)

注意-最后沒有分號。

半冒號本身就是“空語句”,即不執行任何操作的語句。

有時它很有用,但大多數時候都是錯誤的。 例如,此if語句不具有預期的效果:

if (x == y);
{
    z=1;
}

盡管如此,它還是C語言中完全有效的一部分。

使用后

gcc -E file_name.c您將獲得第二個代碼:-

int t; t=a, a=b, b=t;;

這是有效的

相當於

int t; t=a, a=b, b=t;

; // null statement does nothing

暫無
暫無

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

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