C99 printf格式化程序与C++ 11用户定义文字

rub*_*nvb 23 c++ printf c99 code-translation c++11

这段代码:

#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);
}
Run Code Online (Sandbox Code Playgroud)

根据GCC 4.5,适用于C99,C++ 03,C++ 11,但根据GCC 4.7.1,在C++ 11上失败.在PRId64GCC 4.7.1编译之前添加空格.

哪一个是正确的?

eca*_*mur 20

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

2.2翻译阶段[lex.phases]

1 - 翻译语法规则的优先顺序由以下阶段指定.[...]
3.源文件被分解为预处理标记(2.5)和空白字符序列(包括注释).[...]
4.执行预处理指令,扩展宏调用,[...]

并且每2.5个预处理标记[lex.pptoken],user-de fi ned-string-literal是一个预处理标记生成:

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

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

因此,第4阶段的宏扩展PRId64是无关紧要的,因为"%"PRId64已经将其解析为由string-literalud-suffix组成的单个用户定义字符串文字预处理标记. "%" PRId64

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

printf("%"PRId64"\n", val);
Run Code Online (Sandbox Code Playgroud)

printf("%" PRId64"\n", val);     // note extra space
Run Code Online (Sandbox Code Playgroud)

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

  • 伊克.恕我直言用空格写它:`printf("%"PRId64"\n",val);`无论如何都是更好的风格,但它仍然是一个破坏现有代码的变化.顺便提一下,不以下划线开头的ud后缀保留用于将来的标准化,因此该程序"格式错误,无需诊断".参考文献:[N3337](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)2.14.8p10和17.6.4.3.5 (3认同)