C “long”保证和“size\t”一样宽吗`

C “long”保证和“size\t”一样宽吗`,c,language-lawyer,c89,C,Language Lawyer,C89,在寻找unsigned long足以容纳size\u t作为printf参数的证据时,我遇到了两个事实(oid) 首先,这说明long确实不能保证足够大以容纳size\u t。另一方面,我看到这建议在C99之前使用printf(“%lu”,(无符号长)x),x为size\u t 因此,问题是您是否可以假设或保证long足够容纳size\u t在C99之前的中。另一个问题是,是否存在任何保证size\u t可以适用于任何其他标准化整数类型(除了明显的例外,如ssize\u t、ptrdiff\u

在寻找
unsigned long
足以容纳
size\u t
作为
printf
参数的证据时,我遇到了两个事实(oid)

首先,这说明
long
确实不能保证足够大以容纳
size\u t
。另一方面,我看到这建议在C99之前使用
printf(“%lu”,(无符号长)x)
x
size\u t


因此,问题是您是否可以假设或保证
long
足够容纳
size\u t
C99之前的中。另一个问题是,是否存在任何保证
size\u t
可以适用于任何其他标准化整数类型(除了明显的例外,如
ssize\u t
ptrdiff\u t
等)。

没有这种保证

虽然对于实现来说,
long
size\u t
具有相同的大小是常见的,但情况并非总是如此。如注释所示,Windows 64位的
long
size\u t
大小不同

还请注意,实现的
SIZE_MAX
的最小值为
65535
,而
ULONG_MAX
的最小值为
4294967295
2147483647
用于
LONG_MAX
)。(请注意,
SIZE\u MAX
与C99一起出现。)这意味着
SIZE\u t
保证至少为16位,但
无符号长
/
保证至少为32位

编辑:在回答这个问题后,问题有了一些变化。。。因此:

因此,问题是,您是否可以假设或保证,在C99之前,足够长的时间来保持尺寸

即使在C89中也没有此类保证
long
可以是32位和
size\u t
64位。(请参见上面64位Windows中带有MSVC的C89示例。)

另一个问题是,是否有任何保证可以保证size_t适合任何其他标准化整数类型(除了明显的例外,如ssize_t、ptrdiff_t等)

同样,标准也没有这样的保证
size\u t
是另一个标准无符号整数类型的别名(它不能是扩展整数类型,因为C89没有扩展整数类型)

因此,问题是您是否可以假设或保证
long
足够容纳
size\u t
C99之前的

不是
long
,而是
无符号long

在C89/C90中,
size\u t
必须是无符号整数类型。C89/C90中正好有4种无符号整数类型:
无符号字符
无符号短
无符号整数
,和
无符号长
。因此,在C89/C90中,
size\u t
的宽度不能大于
unsigned long
,因此
size\u t
类型的任何值都可以转换为
unsigned long
,而不会丢失信息。(这仅适用于
无符号长
,不适用于

随着
无符号long-long
和扩展整数类型的引入,这种隐式保证在C99中消失了。在C99及更高版本中,
大小\u t
可以比
无符号长
宽。例如,C99实现可能具有32位
long
和64位
long
,并使
size\u t
成为
无符号long
的别名

即使在C89/C90中,您也只能在具有符合要求的C89/C90实现的情况下才能依赖担保。C99之前的编译器通常在C89/C90标准之上提供扩展——例如,编译器可能支持
long-long
,并且可能使
size\u t
成为
unsigned-long
的别名,即使编译器不完全支持C99(或C11)标准

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

printf("sizeof (int) = %lu\n", sizeof (int));
具有未定义的行为,除非
size\u t
恰好是
unsigned long
的别名(即使
size\u t
unsigned long
恰好具有相同的大小)。您需要将值强制转换为正确的类型:

printf("sizeof (int) = %lu\n", (unsigned long)sizeof (int));
对于C99及更高版本,您可以直接打印
size\t
值:

printf("sizeof (int) = %zu\n", sizeof (int));
如果愿意,您可以测试
\uuuu STDC\u VERSION\uuuu
的值,以确定使用哪一个


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

同样,64位windows具有32位长和64位大小。\u tAlso:
size\u t
未签名,
long
s已签名。对于windows和Visual Studio,用于打印大小变量的格式说明符为(%大写I)%I后面可选地跟o、u、x或x,它们将在32位和64位模式下工作。对于GCC,我认为它是%zu(不确定是否可以将其他后缀与%z一起使用)。不幸的是,这个答案似乎被过早地发布了(正如问题所示),这个问题后来完成了,所以这并不能真正回答问题。@skyking-在Visual Studio(2013年及更高版本,可能也是2015年)的情况下,它的C(不是C++)编译器是在C99之前的。