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 预处理令牌 [lex.pptoken]用户定义的字符串文字是一个预处理令牌生产:

2.14.8 用户定义的文字 [lex.ext]

用户定义字符串文字
    字符串文字 ud-suffix
ud-suffix
    标识符

所以第 4 阶段的宏扩展PRId64是无关紧要的,因为"%"PRId64已经被解析为由string-literalud-suffix组成的单个user-defined-string-literal预处理标记。 "%" PRId64

哦,这将是真棒; 每个人都必须改变

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

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

然而!gcc 和 clang 已同意将后缀上没有前导下划线的用户定义字符串文字视为两个单独的标记(根据非良好格式标准),请参阅http://gcc.gnu.org/bugzilla/show_bug.cgi?id =52538所以对于未来版本的 gcc(我认为是 4.8 分支)现有代码将再次工作。

于 2012-08-08T17:09:58.000 回答