2015-06-20 113 views
-1
#define swap(t, x, y) \ 
    do { \ 
    t safe ## x ## y; \ 
    safe ## x ## y = x; \ 
    x = y; \ 
    y = safe ## x ## y; \ 
    } while (0) 

代碼交換類型爲t的參數x和y。這個C宏是什麼意思?

+0

你得到了什麼輸出? – tharif

+1

雙磅符號##用於標記串聯。 Google for same –

+1

爲了保持以下關於C宏的未寫(?)規則,我建議你在所有CAPS中命名你的宏......'#define SWAP(t,x,y)' – pmg

回答

2

##(雙數號符號)運算符在宏定義中給出的宏調用(文本和/或參數)中連接兩個令牌。 Read More

2

雙磅符號##用於令牌串聯。

這就是您的代碼在沒有磅密鑰的情況下的樣子。

#define swap(t, x, y) \ 
    do { \ 
    t safexy; \ 
    safexy = x; \ 
    x = y; \ 
    y = safexy; \ 
    } while (0) 

您需要通過以下規則遵守使用##

  • ##操作時,不能在宏定義的 更換列表中的第一個或最後一個項目。
  • ##運算符前面的項目的最後一個令牌是 與## 運算符後面的項目的第一個令牌級聯。
  • 串聯發生在參數中的任何宏被擴展爲 之前。如果級聯結果的名稱是有效的宏 ,則即使它在通常不可用的上下文中出現,也可用於進一步替換,即使它出現在 。

  • 如果多於一個操作員##和/或操作者#出現在宏定義的 替換列表, 的運算符的計算的順序沒有限定。

欲瞭解更多瞭解read here

2

當你調用這個宏,例如像這樣:

swap(double, a, b); 

它就會通過內嵌代碼替換掉兩個值,即:

do { 
    double safeab; 
    safeab = a; 
    a = b; 
    b = safeab; 
} while (0); 

注意事項:

  • 交換需要一個臨時變量。爲了創建這個變量,類型必須是已知的。 (有些編譯器允許你使用typeof(a),但這不是標準的,因此不便於使用。)
  • 臨時變量的名稱由要通過預處理器的連接運算符##交換的變量的名稱組成。此運算符僅在宏體中可用,並通過將相鄰的令牌粘貼在一起來創建新令牌。請注意,如果其中一個交換操作數是複合的,則名稱創建失敗,例如, a[i]p->x。通過並置創建名稱有點過分謹慎。因爲交換髮生在它自己的範圍內,所以影子變量是安全的,當然這些變量除外。只需在常規命名約定之外選擇一個名字並跨越你的手指。
  • do { ... } while (0)包裝是使宏表現像功能的常用方法,如果它們被用作ifwhile主體的唯一表達式,則它是非常重要的。
  • 最後的反斜槓允許您在各行上傳播宏。習慣上最好是將它們排列好,以便它們不會混淆代碼。

鑑於宏不適用於複合表達式,您不會購買太多。它也不是泛型類型的,因爲當你調用宏時,類型必須是已知的。編寫一個用於交換的小靜態函數;在我看來這更清晰。

C FAQ對type-generic swap宏也有疑問和強烈的意見。

+0

由於你不能交換複合表達式無論如何,我不確定'給定'條款是否真的適用。你只能交換......嗯,我估計,l值。 –

+0

@JonathanLeffler:嗯,你可以交換,比如'a [i]'和'a [j]'或'p-> x'和'p-> y',不是嗎?這不會連接成一個有效的變量名稱,也不是一個「簡單的」單標記表達式。也許「複合表達」不是一個好詞;我在這裏使用了「複合」,因爲它在「複合文字」中使用,即指複合數據類型。 –

+0

順便說一下,我也不確定這個問題完全是關於'##'操作符的,因爲這裏的每個人似乎都假設。原始的,確切地說模糊的問題標題是「這個代碼是如何工作的?」。 –