【问题标题】:Format specifiers for uint8_t, uint16_t, ...?uint8_t、uint16_t、...的格式说明符?
【发布时间】:2011-08-09 08:05:02
【问题描述】:

如果我有一个整数变量,我可以使用sscanf,如下所示,使用格式说明符 %d。

sscanf (line, "Value of integer: %d\n", &my_integer);

在哪里可以找到uint8_tuint16_tuint32_tuint64_t 的格式说明符?

uint64_t 可能有 %lu。

【问题讨论】:

  • %lu 不是 unsigned long 吗?这通常是 32 位。
  • 改用iostreams没问题,适应类型
  • @MSalters:注意对于 64 位目标,Windows 64 unsigned long 是 32 位,而所有 UNIX 和 Linux 64 位 unsigned long 都是 64 位。
  • @Didier Trosset unsigned long 在所有 64 位 UNIX 变体上都不是 64 位。它是使用 gcc 在 64 位 solaris 上的 32 位。我曾经有过痛苦的经历,得知它在 linux 上是 64 位的。
  • @camelccc 从那里的解释来看:unix.org/version2/whatsnew/lp64_wp.html,64 位 solaris 应该是 UNIX 是 LP64 的一个例外。

标签: c++ c++11 scanf


【解决方案1】:

它们在<inttypes.h> 中声明为宏:SCNd8、SCNd16、SCNd32 和 SCNd64。 示例(对于 int32_t):

sscanf (line, "Value of integer: %" SCNd32 "\n", &my_integer);

它们的格式是 PRI (for printf)/SCN (for scan) 然后是 o, u, x, X d, i 对应的说明符然后什么都没有,LEAST, FAST, MAX 然后是大小(显然没有大小最大限度)。其他一些示例:PRIo8、PRIuMAX、SCNoFAST16。

编辑:顺便说一句,related question 询问为什么使用该方法。您可能会发现答案很有趣。

【讨论】:

  • 对于uint32_t 应该是SCNu32SCNi32 代表int32_t
  • -1:它们没有在此处声明,除非作为非标准扩展。
  • @phresnel,关于 int8_t 的问题显然假设 C++0X 或在标准这样做之前从 C99 导入那些的扩展。在第一种情况下,<inttypes.h> 存在,在第二种情况下,假设 <inttypes.h><stdint.h> 同时导入对于我所知道的实现来说是一个相当安全的选择。
  • 由于这是一个流行的问答,建议对一个无关紧要的问题发表评论:scanf() 格式的尾随 '\n' 肯定有问题。
【解决方案2】:

正如其他人所说,包含定义格式宏的 <stdint.h> 标头。然而,在 C++ 中,在包含 __STDC_FORMAT_MACROS 之前定义它。来自 stdint.h:

/* The ISO C99 standard specifies that these macros must only be
   defined if explicitly requested.  */
#if !defined __cplusplus || defined __STDC_FORMAT_MACROS

【讨论】:

  • 并且根据 C++0X,“ 定义的宏是无条件提供的。特别是,在 C 标准的脚注 182 中提到的符号 __STDC_FORMAT_MACROS 在 C++ 中不起作用。 "但是定义 __STDC_FORMAT_MACROS 可能有助于未更新为遵循 C++0X 的扩展。
【解决方案3】:

根据 ISO/IEC 9899:TC27.19.6 格式化输入/输出函数,没有这样的格式说明符(所以我怀疑 C+ +2003)。尽管 C99 的inttypes.h 中提供了一些#define-macros,但cinttypesinttypes.h 并不是当前标准的一部分。当然,固定大小的整数类型也是非标准的。

无论如何,我强烈建议改用流:

<any_type> x;
f >> x;

然后完成。例如:

std::stringstream ss;
uint32_t u;
std::cin >> u;

这样做的好处是,在将来的某个时候,更改变量的类型不会导致一连串细微的错误和未定义的行为。

【讨论】:

  • 使用 ">>" 似乎比 fscanf 慢得多,在 VC++ 2010 上慢了 2-3 次
  • @sergtk:这是一个功能。默认情况下,iostream 与 C 函数同步。您可以禁用它,结果将是 iostream 的速度至少一样快。
  • 我想你的意思是 std::ifstream.sync_with_stdio(false); .这并不能合理地提高速度。此外,如果字符串由
  • @sergtk:嗯,不在我的基准测试中:stackoverflow.com/a/9747716/76722stackoverflow.com/a/9212163/76722。而且我不确定您为什么要使用&lt;&lt;,然后使用sscanf 作为fscanf 的替代品。
  • 第一个链接包含读取字符时的测试,这不涉及转换类型。第二个链接更有趣,因为它已经包含 int-s。但是我们使用了不同的编译器。我主要使用 int-s 和 float-s 进行测试。更有趣的是,实际上我测试中的所有文件读取仍然使用 std::ifstream。但最初它用于读取带有“
【解决方案4】:

在C中,header为&lt;inttypes.h&gt;,格式如SCNX8、SCNd16。

同样的标头可能也适用于 C++。

【讨论】:

  • &lt;inttypes.h&gt; 已与 &lt;stdint.h&gt;(声明 typedef int8_t 和朋友)同时导入 C++ 标准,正式在 C++0X 中,但实际上可作为扩展在与 C99 的实现有密切关系的实现中。
【解决方案5】:

读取uint64_t(typedef unsigned long long int)的正确格式是scanf而不是sscanf"%" SCNu64,打印也是SCNu64 例子。在您阅读的代码中,例如 my_integer 变量,然后您执行 scanf ("Value of integer:%" SCNu64, &amp; my_integer); 和 printf 一样写。

【讨论】:

    【解决方案6】:

    您可以在&lt;cstdint&gt; 中检查C++ 类型或在&lt;types.h&gt; 中检查C 类型。然后您可以指定当前在您的机器上编译的格式。 如果变量为unsigned,则需要使用%u,如果变量为signed,则使用%d。对于小于 32 字节的变量,您不必指定长前缀。

    在我的配置中我有64位程序,所以我的uint64_t被编译为unsigned long long int,所以这意味着使用%llu。如果您的程序将编译为 32 位,您可以使用 %lu,因为 uint64_t 将编译为 unsigned long int

    但是谁还在使用 x86? :),一般来说:

    uint8_t, uint16_t, uint32_t - %u
    uint64_t - %llu
    int8_t, int16_t, int32_t - %d
    int64_t -%lld
    

    【讨论】:

    • 请在您的答案中添加一些解释,以便其他人可以从中学习
    【解决方案7】:

    请参阅this 了解 sscanf 的用法。

    这些数据类型在 stdint.h 中定义。 stdint.h 参考here

    沙士

    【讨论】:

    • 引用没有回答。它主要告诉你不了解自己。
    • 我不相信复制,如果可以通过网络获得,请粘贴! + 这就像加入点,sscanf & stdint,你不觉得吗?
    • 但是 stackoverflow 的答案本身应该保持有效。至少告诉 cplusplus.com/reference/clibrary/cstdio/sscanf 在哪里提到了如何格式化 int64 等。
    猜你喜欢
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2016-02-13
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多