`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)
,x
是 size_t
.
所以问题是您是否可以假设或者您是否认为 运行 认为 long
足以在 C99 之前 中容纳 size_t
.另一个问题是是否存在 size_t
适合任何其他标准化整数类型的 gua运行tee(除了明显的例外,如 ssize_t
、ptrdiff_t
等).
没有这样的保证。
虽然实现 long
和 size_t
的大小相同很常见,但情况并非总是如此。正如评论中所说 Windows 64 位 long
和 size_t
.
的大小不同
另请注意,实施的 SIZE_MAX
的最小值为 65535
,而 ULONG_MAX
的最小值为 4294967295
(2147483647
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 char
、unsigned short
、unsigned int
、unsigned 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_t
和 unsigned 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 年标准。)
当寻找 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)
,x
是 size_t
.
所以问题是您是否可以假设或者您是否认为 运行 认为 long
足以在 C99 之前 中容纳 size_t
.另一个问题是是否存在 size_t
适合任何其他标准化整数类型的 gua运行tee(除了明显的例外,如 ssize_t
、ptrdiff_t
等).
没有这样的保证。
虽然实现 long
和 size_t
的大小相同很常见,但情况并非总是如此。正如评论中所说 Windows 64 位 long
和 size_t
.
另请注意,实施的 SIZE_MAX
的最小值为 65535
,而 ULONG_MAX
的最小值为 4294967295
(2147483647
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 holdsize_t
in pre C99.
不是long
,而是unsigned long
。
在C89/C90中,size_t
必须是无符号整型。 C89/C90中正好有4种无符号整数类型:unsigned char
、unsigned short
、unsigned int
、unsigned 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_t
和 unsigned 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 年标准。)