2009-07-30 49 views
5

我有這樣一個宏(不完全,但功能還是相當相當)GCC宏##連接符:差異在Visual-C++和

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value 
... 
STRUCTMEMBER(Item,1); 

這工作完全在Visual C++,但gcc 3.4.5(MingGW)產生以下錯誤:

pasting "." and "Item" does not give a valid preprocessing token

這也發生在我使用「 - >」運算符時。我沒有發現關於連接的提示,這些操作符的使用是被禁止的。

有沒有人有想法?

+1

http://gcc.gnu.org/ml/gcc-help/2003-04/msg00213.html有什麼用? – AakashM 2009-07-30 13:33:07

+0

空間故意? – EFraim 2009-07-30 13:33:29

回答

7

也許Visual C++將兩個空間粘貼在一起以創建另一個空間。不是空格是令牌,但它可以讓你的代碼工作。

object.member不是一個標記,它是三個標記,所以你不需要標記粘貼來實現你描述的宏。只要刪除'##',它應該無處不在。

[編輯:剛剛檢查,並且使用##形成非有效標記的結果未定義。所以GCC允許拒絕和MSVC允許忽略它並沒有進行粘貼,據我可以告訴]

4

gcc c preprocessor docs

However, two tokens that don't together form a valid token cannot be pasted together.

structure.member不是一個單一的令牌。

在這種情況下,您不需要使用##(令牌串聯)運算符。你可以刪除它。下面是一個例子用gcc 4.2.4在Linux上進行了測試:

#include <stdio.h> 

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value 

struct { 
    const char* member1; 
}GlobalStructInstance; 

int main(void) 
{ 

    STRUCTMEMBER(member1, "Hello!"); 

    printf("GlobalStructInstance.member1 = %s\n", 
      GlobalStructInstance.member1); 

    return 0; 
} 
5

按照C標準中,「##」預處理運算的結果必須是「預處理記號」或結果是未定義的(C99 6.10 .3.3(3) - ##運算符)。

預處理標記的名單(C99 6.4(3) - 詞法元素):

header names, identifiers, preprocessing numbers, character constants, string literals, punctuators, and single non-white-space characters that do not lexically match the other preprocessing token categories.

GCC可以讓你知道你正在進入不確定的領土。 MSVC對未定義的結果非常滿意(這就是你期望發生的事情)。

請注意,如果您還沒有創建單個令牌,那麼您不需要令牌粘貼操作符。通常(我確定可能有一個例外或兩個),用空格分隔的2個令牌相當於2個未被空格分隔的令牌 - 就像你的例子。