关于C#:C99 printf格式化程序与C 11用户定义的文字

C99 printf formatters vs C++11 user-defined-literals

此代码:

1
2
3
4
5
6
7
8
9
10
11
12
#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"\
"
,val);
   exit(0);
}

根据GCC 4.5适用于C99,C 03,C 11,但根据GCC 4.7.1在C 11上失败。在PRId64之前添加一个空格可以让GCC 4.7.1对其进行编译。

哪个是正确的?


gcc 4.7.1是正确的。根据标准,

c++11

2.2 Phases of translation [lex.phases]

1 - The precedence among the syntax rules of translation is speci???ed by the following
phases. [...]
3. The source ???le is decomposed into preprocessing tokens (2.5) and sequences of white-space characters
(including comments). [...]
4. Preprocessing directives are executed, macro invocations are expanded, [...]

对于每2.5个预处理令牌[lex.pptoken],用户定义的ned-string-literal是一种预处理令牌生成:

2.14.8 User-de???ned literals [lex.ext]

user-de???ned-string-literal:
string-literal ud-suffix
ud-suffix:
identifier

因此PRId64的第4阶段宏扩展是无关紧要的,因为"%"PRId64已经被解析为单个由用户定义的,由字符串文字"%"和ud后缀PRId64

哦,这太棒了;每个人都必须改变

1
2
printf("%"PRId64"\
"
, val);

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

但是! gcc和clang同意将用户定义的字符串文字(在后缀上没有前划线的情况下)视为两个单独的标记(根据格式不正确的标准),请参阅http://gcc.gnu.org/bugzilla/show_bug.cgi?id = 52538,因此对于gcc的未来版本(我认为是4.8分支),现有代码将再次起作用。