62

次のコードを検討してください。

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)

期待される出力はX = 1 and VA_ARGS = 2, 3両方のマクロであり、GCC で得られるものですが、MSVC はこれを次のように展開します。

X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =

つまり、__VA_ARGS__複数の引数に分割されるのではなく、単一の引数として展開されます。

これを回避する方法はありますか?

4

3 に答える 3

60

編集: この問題は 、最近の MSVC で/Zc:preprocessorまたはオプションを使用することで解決される可能性があります。/experimental:preprocessor詳細はこちらをご覧 ください

MSVC のプリプロセッサは、標準仕様とはかなり異なる動作をしているようです。
おそらく、次の回避策が役立ちます。

#define EXPAND( x ) x
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) EXPAND( F(__VA_ARGS__) )
于 2011-02-27T17:24:54.253 に答える
28

次の Microsoft サポートの問題を投稿しました。

__VA_ARGS__次のプログラムでは、プリコンパイラが正しく展開されないため、コンパイル エラーが発生します。

#include <stdio.h>

#define A2(a1, a2) ((a1)+(a2))

#define A_VA(...) A2(__VA_ARGS__)

int main(int argc, char *argv[])
{
    printf("%d\n", A_VA(1, 2));
    return 0;
}

プリプロセッサは、printf を次のように展開します。 printf("%d\n", ((1, 2)+()));

printf("%d\n", ((1)+(2))) の代わりに;

Microsoft コンパイラ チームの開発者から、次の満足のいく回答を受け取りませんでした。

Hi: この場合、Visual C++ コンパイラは正しく動作しています。最初のマクロ呼び出しで「...」に一致するトークンが結合されて単一のエンティティを形成するという規則 (16.3/p12) と、引数置換の前にサブマクロが展開されるという規則 (16.3.1/p1 ) この場合、コンパイラは A2 が 1 つの引数で呼び出されたと見なします。そのため、エラー メッセージが表示されます。

于 2011-09-18T06:11:50.843 に答える
0

使用している MSVC のバージョンは何ですか? Visual C++ 2010 が必要です。

__VA_ARGS__ C99 で初めて導入されました。MSVC は C99 をサポートしようとしなかったため、サポートは追加されませんでした。

ただし、現在__VA_ARGS__は新しい C++ 標準である C++2011 (以前は C++0x として知られていた) に含まれており、Microsoft はこれをサポートする予定であるため、MSVC の最近のバージョンでサポートされています。

.cppところで、このサポートを受けるには、ソース ファイルにサフィックスを使用する必要があります。MSVC は長い間 C フロントエンドを更新していません。

于 2011-09-18T06:28:13.243 に答える