【问题标题】:Printing size_t using printf in GNU systems在 GNU 系统中使用 printf 打印 size_t
【发布时间】:2017-09-06 20:09:14
【问题描述】:

当我阅读这个article时,我看到了这段:

同样,不要努力去迎合 long 小于预定义类型(如 size_t)的可能性。比如下面的代码就可以了:

printf ("size = %lu\n", (unsigned long) sizeof array);
printf ("diff = %ld\n", (long) (pointer2 - pointer1));

1989 标准 C 要求它工作,我们只知道一个反例:Microsoft Windows 上的 64 位程序。我们将离开它 对于那些想要将 GNU 程序移植到那个环境的人来说 知道怎么做。

1989 年标准 C 真的允许这种代码吗?

【问题讨论】:

  • 对于 C99 之前的版本,long/unsigned long 是最宽的标准类型 - 几乎不会丢失转换为最宽的整数类型。当然可以使用rintf ("size = %.0f\n", 1.0* sizeof array);
  • @chux 但该代码符合标准吗?
  • 它是合规的(除了可能在pointer2 - pointer1 中溢出)。问题仍然存在,它会打印预期的结果吗? (它被截断了吗?)
  • 大致是“在 C90 中,如果有什么标准可以工作,那就是这个”。它不能保证在所有情况下都有效,但它可以在大多数情况下工作。并且没有标准指定的替代方案可以更好地工作。从 C99 开始,您应该使用z(用于size_t)和t(用于ptrdiff_t)大小修饰符:"%zu; %td\n"
  • 这应该适用于所有情况void print_size(size_t sz) { if (sz >= 10) { print_size(sz/10); } printf("%u", (unsigned) (sz%10)); }

标签: c printf gnu c89 size-t


【解决方案1】:

问的问题:

1989 年标准 C 真的允许这种代码吗?

是的,如果“允许”我们的意思是“这将编译和运行,做一些合理的事情并且不会触发未定义的行为”(而不是“这将做我想要的”)。这两种情况略有不同。

对于size_t,如果结果太大会被截断。对于ptrdiff_t,如果太大,结果将由实现定义。

但是,最新版本的 Visual Studio (_MSC_VER >= 1800) 支持 zt 转换(无论如何都是 C++11 支持所必需的),因此您可以使用:

size_t size;
printf("size = %zu\n", size);
ptrdiff_t diff;
printf("diff = %td\n", diff);

这也适用于其他系统(GNU、BSD、Darwin)。对于旧版本的 Visual Studio,有替代方案,但需要在不同平台上使用不同的格式字符串。

关于 GNU 编码标准的说明

GNU 编码标准适用于 GNU 组织,它有一些非常具体的目标,并且不太关心支持 Windows。我会对他们的编码标准持保留态度,除非您有特定的理由遵循它们(例如,您希望您的项目将来成为 GNU 项目)。

【讨论】:

  • 不,标准不保证 %zd 将适用于 ptrdiff_t 参数 - 但它不需要,因为 ptrdiff_t 参数的正确格式是 @ 987654330@。 (%zd 是对应于无符号类型 size_t 的有符号类型。该类型没有可移植的名称——即使 POSIX 也不保证 ssize_t 符合条件。)
  • @KeithThompson:请随意编辑答案,我找不到 Visual Studio 的文档。
  • 其实我并不打算完全遵循这些规则,我阅读了其他约定,而我正在阅读这个,只是为了看看我是否可以找到我在其他约定中遗漏的东西,或者什么我喜欢。
猜你喜欢
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
相关资源
最近更新 更多