【问题标题】:How to printf uint64_t? Fails with: "spurious trailing ‘%’ in format"如何打印 uint64_t?失败:“格式中的虚假尾随‘%’”
【发布时间】:2011-11-15 06:35:47
【问题描述】:

我写了一个很简单的printf uint64_t的测试代码:

#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t ui64 = 90;
  printf("test uint64_t : %" PRIu64 "\n", ui64);
  return 0;
}

我使用ubuntu 11.10(64位)和gcc 4.6.1版本编译,但是失败了:

main.cpp: In function ‘int main()’:
main.cpp:9:30: error: expected ‘)’ before ‘PRIu64’
main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]

【问题讨论】:

  • 您似乎将 C 代码编译为 C++,这是您的错误。如果您将文件重命名为main.c 并使用 gcc 进行编译,则一切正常。
  • 使用 gcc 或 clang,最好指定 -std=c11 或您使用的标准版本。这可以捕捉到这个错误和其他错误。我也至少推荐-Wall -Wextra -Wpedantic -Wconversion

标签: c++ c


【解决方案1】:

ISO C99 标准规定,这些宏只有在明确要求时才可以定义。

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work

【讨论】:

  • @Dan,如果它解决了您的问题,请不要忘记将答案标记为已接受(单击左侧的复选标记图像)。
  • 嗯,只包括标题就足够了。 __STDC_FORMAT_MACROS 宏只需要包含在 C++ 中。
  • @Jens:确实; __STDC_FORMAT_MACROS 仅出现在 C99 的脚注中,表明 C++ 仅在存在请求的情况下定义这些宏。然而 C++ 委员会选择忽略这个建议:例如在 n3242 草案 27.9.2/3 中:注意: 定义的宏是无条件提供的。特别是,在 C 标准的脚注 182 中提到的符号 __STDC_FORMAT_MACROS 在 C++ 中不起作用。 因此,当编译器赶上来时,我们在 C 或 C++ 中都不需要__STDC_FORMAT_MACROS
  • @John Marshall g++ 4.7.3 似乎需要宏,即使包含 也是如此。
  • @Eric:显然 g++ 4.7.3 还没有跟上!事实上,您可能正在使用早于this bug fix 的 glibc 版本。正如该 glibc 报告中所讨论的,您的 g++ 4.7.3 的 libstdc++ 具有解决此问题的代码。如果您使用-std=c++0x 进行编译,并且可能使用#include 而不是,我相信它会在您不提供__STDC_FORMAT_MACROS 的情况下提供格式宏。
【解决方案2】:

在 Centos 5.x 下编译 memcached 时,我遇到了同样的问题。

解决办法是至少将gcc和g++升级到4.4版本。

确保在编译之前将您的 CC/CXX 设置(导出)为正确的二进制文件。

【讨论】:

    【解决方案3】:

    由于您已包含 C++ 标记,因此您可以使用 the {fmt} library 并完全避免 PRIu64 宏和其他 printf 问题:

    #include <fmt/core.h>
    
    int main() {
      uint64_t ui64 = 90;
      fmt::print("test uint64_t : {}\n", ui64);
    }
    

    基于此库的格式化工具被提议用于 C++20 中的标准化:P0645

    免责声明:我是 {fmt} 的作者。

    【讨论】:

    • 酷!是不是也类似于sscanf
    • 很有可能。我们正在研究替换 scanf 的可能性。
    • 太棒了!另外我想知道std::to_string() 的区域独立和/或区域可选版本是否有进展。 cppreference 页面仍然只链接到std::to_chars(),这并不是人们真正需要的。我想知道fmt 和/或 c++20 是否处理它。
    • std::to_string 可能会保持原样,但std::format 允许您控制是否使用区域设置(默认情况下它不使用区域设置)。
    猜你喜欢
    • 2018-04-26
    • 1970-01-01
    • 2018-06-26
    • 2016-02-27
    • 1970-01-01
    • 2011-03-21
    • 2016-11-24
    • 1970-01-01
    • 2015-12-07
    相关资源
    最近更新 更多