【问题标题】:How to print size_t and ptrdiff_t using printf in ANSI C (C89)如何在 ANSI C (C89) 中使用 printf 打印 size_t 和 ptrdiff_t
【发布时间】:2017-05-28 18:44:07
【问题描述】:

我知道这在 SO 上已被多次质疑,但我的问题是 ANSI C (C89) 所特有的。

在 C99 中有子说明符 zt,它们在 ANSI C 中不受支持。

如何使用p 说明符?

【问题讨论】:

  • AFAIK ANSI 自动采用 ISO 标准,因此您应该可以使用相同的标准。如果您的意思是明确的 C89/90 ():没有办法。请注意,C99 不是标准 C;那将是 C11。
  • @levengli:请不要说这种废话! size_t 不能是 intptrdiff_t 不会出现在 int 不足的系统上,例如大多数 64 位架构和一些 8/16 位架构
  • @DietrichEpp 是的,但是每个 C 标准都明确地使其前身无效,所以“C 标准”总是指最新的。
  • @Olaf 争论这个有什么意义? OP 明确询问 C89。 OP 比你更了解他的环境,所以如果他询问 C89,只需提供答案,或者不提供。
  • @Olaf:2011 ISO C 标准确实是美国国家标准协会(ANSI)目前认可的标准。但是您应该知道实际上 nobody 将 C11 称为“ANSI C”。即使没有澄清的“(C89)”,很明显OP正在询问C89 / C90。 OP的错误(例如)是将该语言称为“ANSI C”。如果您想指出这一点,那很好,但是假装 OP 真的想询问以后的标准是没有帮助的。

标签: c printf c89


【解决方案1】:

size_t 是实现定义的无符号整数类型。 ptrdiff_t 是实现定义的有符号整数类型。

在 C89/C90(通常,但严格来说不正确,称为“ANSI C”)中,这些类型没有特殊的格式说明符。但最广泛的整数类型是long intunsigned long int,它们当然有自己的格式说明符。

要打印size_t 值,请将其转换为unsigned long 并使用"%lu"

要打印ptrdiff_t 值,请将其转换为long 并使用"%ld"

请注意,如果您的代码随后使用 C99 或 C11 编译器编译,size_t 和/或ptrdiff_t 可能比long 宽,并且代码可能会失败。 (我记得 64 位 Windows 界面有 32 位 long,所以这在实践中可能是个问题。)

在 C99 及更高版本中,只需将 %zu 用于 size_t,将 %td 用于 ptrdiff_t。如果您希望您的代码真正可移植,请考虑使用#if 来测试__STDC_VERSION__ 的值。

如果您的编译器仅部分符合 C99 或 C11,您也可能会遇到问题。您可能有一个不完全支持 C99 的编译器,但它确实提供了 long long。但是为了打印size_t 值,只有当您打印的值实际上超过ULONG_MAX(至少为232-1)时,这才会成为问题。对于ptrdiff_t 值,只要不超过LONG_MAX(至少为231-1),转换为long 即可。

最后,如果您碰巧知道要打印的值不是太大,您可以通过转换为int 并使用%d 来摆脱困境。我建议转换为unsigned longlong,但int 可以用于快速脏代码。

如何使用p 说明符?

不,%p 仅适用于 void* 类型的指针,并且在任何情况下,输出格式都是实现定义的(通常是十六进制,但我见过其他表示形式)。

【讨论】:

  • C89 说“有四种有符号整数类型,指定为有符号字符、短整数、整数和长整数”。这条规定的问题在于,实际上没有任何现有的主要实施遵循它。 size_t 可以很好地定义为 long long unsigned int__uint64 或类似的。你要给谁打电话?
  • @n.m.:支持long long unsigned int 并且不会针对任何使用它发出至少警告消息的编译器不是符合标准的 C89/C90 编译器。 long long unsigned int 是 C89/C90 中的语法错误。
  • “不是一个符合 C89/C90 的编译器”这是一个非常正确的观察,也是一个非常没用的观察。这是你的 MSVC,去写一些代码。不合规?谁在乎?
  • @BiteBytes: %p 需要void* 类型的参数。指针不是整数,它们不能安全地互换使用。将%pvoid* 以外的任何类型的参数一起使用具有未定义的行为。 (将%pchar*unsigned char*signed char* 一起使用也可能有效,但无论如何我都会转换为void*。)
  • @n.m.:我宁愿将size_t 转换为unsigned long 并使用%u 打印。只要打印的值不超过 2^32-1,就可以保证打印正确的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 2019-01-26
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
相关资源
最近更新 更多