簡體   English   中英

功能類宏中的交換功能

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

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