23

このコード:

#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc,char **argv)
{
   uint64_t val=1234567890;
   printf("%"PRId64"\n",val);
   exit(0);
}

GCC 4.5 に従ってC99C++03、 C++11 で動作しますが、GCC 4.7.1 に従って C++11 では失敗します。前にスペースを追加すると、GCC 4.7.1 でコンパイルできます。PRId64

どちらが正しいですか?

4

1 に答える 1

20

gcc 4.7.1 が正しいです。規格によると、

2.2 翻訳の段階 [lex.phases]

1 - 変換の構文規則間の優先順位は、次のフェーズによって指定されます。[...]
3. ソース ファイルは、前処理トークン (2.5) と一連の空白文字 (コメントを含む) に分解されます。[...]
4. 前処理ディレクティブが実行され、マクロ呼び出しが展開されます。[...]

また、2.5 Preprocessing tokens [lex.pptoken] に従ってuser-defined-string-literalは前処理トークンの生成です。

2.14.8 ユーザー定義リテラル [lex.ext]

ユーザー定義文字列リテラル:
    文字列リテラル ud-suffix
ud-suffix :
    識別子

したがって、 はすでにstring-literalud-suffixで構成される単一のユーザー定義の文字列リテラル前処理トークンとして解析されているため、 のフェーズ 4 マクロ展開PRId64は無関係です。"%"PRId64 "%" PRId64

ああ、これは素晴らしいことです。誰もが変わらなければならない

printf("%"PRId64"\n", val);

printf("%" PRId64"\n", val);     // note extra space

でも!gcc と clang は、ユーザー定義の文字列リテラルをサフィックスの先頭にアンダースコアを付けずに 2 つの別個のトークンとして扱うことに同意しました (整形式ではない基準に従って)。http://gcc.gnu.org/bugzilla/show_bug.cgi?id を参照してください。 =52538したがって、gcc の将来のバージョン (4.8 ブランチだと思います) では、既存のコードが再び機能するようになります。

于 2012-08-08T17:09:58.000 に答える