`long` 是否保证与 `size_t` 一样宽

Was `long` guaranteed to be as wide as `size_t`

当寻找 unsigned long 足以支持 size_t 作为 printf 论证的证据时,我 运行 分为两个事实(oid)。

首先有这个 answer stating that long is indeed not guaranteed to be large enough for size_t. On the other hand I saw this answer 建议在 C99 之前使用 printf("%lu", (unsigned long)x)xsize_t.

所以问题是您是否可以假设或者您是否认为 运行 认为 long 足以在 C99 之前 中容纳 size_t .另一个问题是是否存在 size_t 适合任何其他标准化整数类型的 gua运行tee(除了明显的例外,如 ssize_tptrdiff_t 等).

没有这样的保证。

虽然实现 longsize_t 的大小相同很常见,但情况并非总是如此。正如评论中所说 Windows 64 位 longsize_t.

的大小不同

另请注意,实施的 SIZE_MAX 的最小值为 65535,而 ULONG_MAX 的最小值为 42949672952147483647 LONG_MAX). (注意 SIZE_MAX 出现在 C99 中。)这意味着 size_t 保证至少是 16 位,但 unsigned long / long 保证至少是 32-位.

编辑: 在这个答案之后问题发生了一点变化......所以:

所以问题是您是否可以假设或保证在 C99 之前的 long 足以容纳 size_t。

即使在 C89 中也没有这样的保证。 long 可以是 32 位,size_t 可以是 64 位。 (请参阅上面 Windows 64 位中使用 MSVC 的 C89 示例。)

另一个问题是是否存在任何保证 size_t 适合任何其他标准化整数类型(除了像 ssize_t、ptrdiff_t 等等)。

标准也没有这样的保证。 size_t 是另一种标准无符号整数类型的别名(它不能是扩展整数类型,因为 C89 没有扩展整数类型)。

So the question is could you assume or were you guaranteed that long were enough to hold size_t in pre C99.

不是long,而是unsigned long

在C89/C90中,size_t必须是无符号整型。 C89/C90中正好有4种无符号整数类型unsigned charunsigned shortunsigned intunsigned long。因此在C89/C90中,size_t不能宽于unsigned long,因此任何size_t类型的值都可以转换为unsigned long 不丢失信息。 (这仅适用于 unsigned long,不适用于 long。)

随着 unsigned long long 扩展整数类型 的引入,这种隐含的保证在 C99 中消失了。在 C99 及更高版本中,size_t 可以比 unsigned long 更宽。例如,C99 实现可能具有 32 位 long 和 64 位 long long,并使 size_t 成为 unsigned long long.

的别名

即使在 C89/C90 中,您也只有在具有符合要求的 C89/C90 实现时才能依赖保证。 C99 之前的编译器通常在 C89/C90 标准之上提供扩展——例如,编译器可能支持 long long,并且可能使 size_t 成为 [=28= 的别名],即使编译器不完全支持 C99(或 C11)标准。

问题是关于 printf。请记住,printf 的参数必须 是格式字符串的适当类型。这个:

printf("sizeof (int) = %lu\n", sizeof (int));

具有未定义的行为,除非 size_t 恰好是 unsigned long 的别名(即使 size_tunsigned long 恰好具有相同的大小)。您需要将值转换为正确的类型:

printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));

对于 C99 及更高版本,您可以直接打印 size_t 个值:

printf("sizeof (int) = %zu\n", sizeof (int));

如果喜欢,您可以测试 __STDC_VERSION__ 的值来确定使用哪一个。

(关于 C 标准版本的说明。第一个 C 标准于 1989 年由 ANSI 发布。它于 1990 年由 ISO 重新发布,添加了额外的样板部分。因此 C89 和 C90 是两个不同的文件,描述相同的语言。后来的C99和C11标准由ISO发布。所有三个ISO C标准都被ANSI正式采用。所以严格来说"ANSI C"应该指的是ISO C11——但由于历史原因,这个短语仍然是用于指代 1989 年标准。)