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

时间:2012-08-08 17:05:13

标签: c++ c++11 printf c99 code-translation

此代码:

#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);
}

适用于C99C++03C++11 according to GCC 4.5,但在C++11 according to GCC 4.7.1上失败。在PRId64之前添加空格让GCC 4.7.1编译它。

哪一个是正确的?

1 个答案:

答案 0 :(得分: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]

     

用户自定义网络连接-字串文本
   string-literal ud-suffix
   UD-后缀
  标识符

因此PRId64的第4阶段宏扩展无关紧要,因为"%"PRId64已被解析为单个 user-de fi ned-string-literal 预处理令牌,包含 string-literal "%" ud-suffix PRId64

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

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分支,我认为)现有代码将再次工作。