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

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

本文关键字:用户 定义 文本 C++11 printf 格式化 程序 C99      更新时间:2023-10-16

此代码:

#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 适用于 C99、C++03、C++11,但根据 GCC 4.7.1 在 C++11 上失败。在PRId64之前添加一个空格可以让GCC 4.7.1编译它。

哪一个是正确的?

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

C++11

2.2 翻译阶段

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

根据 2.5 个预处理令牌 [lex.pptoken]用户定义的字符串文本是预处理令牌生产:

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

用户定义的字符串文字
    字符串文字 ud 后缀
ud-后缀
    标识符

因此,PRId64的阶段 4 宏扩展是无关紧要的,因为"%"PRId64已经被解析为由字符串文字"%"ud-后缀 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 分支)现有代码将再次工作。