[英]Swap function in Function-Like Macros
瀏覽以下C代碼
# define swap(a,b) temp=a; a=b; b=temp;
main( )
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j)
swap ( i, j );
printf ( "%d %d %d", i, j, temp);
}
編譯器輸出:
10 0 0
我期待這個輸出
10 5 0
我為什么錯?
這是缺乏牙箍。 這是宏的常見缺陷之一。 讓我們看看發生了什么:
if(i > j)
swap(i, j);
變為:
if(i > j)
temp = a; a = b; b = temp;;
更具可讀性:
if(i > j)
temp = a;
a = b;
b = temp;
線a = b;
和b = temp;
將永遠被執行,他們落在if
身體之外。
在if
或宏周圍放置大括號。
使用do{
... }while(0)
定義類似語句的宏更好, }while(0)
就像(見這個 ):
#define swap(a,b) do { int temp=a; a=b; b=temp; } while(0)
由於do{
.... }while(0)
構建體正確地理解(甚至當時或else
條件等等的一部分...如在其他答復說明。
實際上,如果你用temp
參數調用swap
(例如swap(temp,xx)
),或者如果你使用副作用的第二個參數(例如swap(x,y++)
將增加y
兩次而不是做你想做的事。
一個迂腐強大的swap
可能會在預處理級別使用連接 ,並使用一些獨特的計數器,如GCC特定的__COUNTER__
預定義宏來生成唯一符號(而不是temp
)
你的問題是這行中的if條件:
if( i > j)
swap ( i, j );
在預處理器替換了您的define之后,這些行看起來如下所示:
if( i > j)
temp=a; a=b; b=temp;
您期望的是以下內容:
if( i > j)
{temp=a; a=b; b=temp;}
這可以通過將您的定義更改為
#define swap(a,b) {temp=a; a=b; b=temp;}
編輯:正如其他人所提到的,更強大的解決方案是將宏定義為
#define swap(a,b) do{temp=a; a=b; b=temp;}while(1)
這仍然需要手動聲明變量temp
。
可以在此處找到類型無關交換宏的一個很好的示例: https : //stackoverflow.com/a/3982430/5237890
您應該在宏聲明中添加花括號來解決您的問題。
此外,如果要交換基本類型(例如int) ,則可以使用XOR運算符交換值而不使用其他變量。
#define swap(a, b) { a ^= b; b ^= a; a ^= b; }
另一個問題是這條線
if( i > j)
在您的情況下,i = 5且j = 10,因此不執行swap()
行的第一個語句。 正如@Kninnug指出的那樣(差不多),實際上你的代碼沒有花括號
if(i > j)
temp = i;
i = j
j = temp;
現在,由於I = 5且j = 10,只執行最后兩行,因此I變為10(j的值),j變為零(temp的值)。
當使用類似函數的宏時,編譯器只需用宏聲明中的文本替換調用函數的代碼中的文本。 在if語句之后你沒有使用大括號,如果你只需要執行一行代碼就可以了。 但是當編譯器為宏函數執行文本替換時,現在需要在if語句下嵌套三行代碼。
在線周圍添加花括號Swap ( a, b )
將解決您的問題。 或者,您可以在宏聲明中的三行代碼周圍放置花括號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.