[英]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.