代码之家  ›  专栏  ›  技术社区  ›  skyking

“long”保证与“size_t”一样宽`

  •  4
  • skyking  · 技术社区  · 9 年前

    寻找证据时 unsigned long 足以容纳 size_t 为了与…争论 printf 我遇到了两个事实。

    首先是这个 answer 声明: long 确实不能保证足够大 大小(_t) 另一方面,我看到了 answer 建议使用 printf("%lu", (unsigned long)x) 在C99之前, x 属于 大小(_t) .

    所以问题是你能假设还是保证 长的 足以容纳 大小(_t) 在里面 C99之前 另一个问题是是否有任何保证 大小(_t) 将适用于任何其他标准化整数类型(除了明显的例外,如 ssize_t , ptrdiff_t 等等)。

    2 回复  |  直到 7 年前
        1
  •  7
  •   ouah    9 年前

    没有这样的保证。

    虽然实现通常具有相同的大小 long size_t ,情况并非总是如此。如注释中所述,Windows 64位具有不同的大小 长的 大小(_t) .

    还要注意 SIZE_MAX 对于一个实现 65535 而最小值 ULONG_MAX 4294967295 ( 2147483647 对于 LONG_MAX ). (注意 大小_最大 与C99一起出现。)这意味着 大小(_t) 保证至少为16位,但 unsigned long / 长的 保证至少为32位。

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

    所以问题是,你是否可以假设或者你是否保证在C99之前的版本中保持size_t的时间足够长。

    即使在C89中也没有这种保证。 长的 可以是32位 大小(_t) 64位。(参见C89示例,在64位以上的Windows中使用MSVC。)

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

    本标准同样没有此类保证。 大小(_t) 是另一个标准无符号整数类型的别名(它不能是扩展整数类型,因为C89没有扩展整数类型)。

        2
  •  3
  •   Keith Thompson    8 年前

    所以问题是你能假设还是保证 long 足以容纳 size_t 在里面 C99之前 .

    长的 但是 unsigned long .

    在C89/C90中, 大小(_t) 必须是无符号整型。正好有4个 无符号整数类型 在C89/C90中: unsigned char , unsigned short , unsigned int 无符号长 因此 C89/C90中 , 大小(_t) 不能大于 无符号长 ,因此任何类型的值 大小(_t) 可以转换为 无符号长 而不会丢失信息。(这仅适用于 无符号长 ,不到 长的 .)

    这种隐含的保证在C99中消失了 unsigned long long 扩展整数类型 在C99及以后, 大小(_t) 可以比 无符号长 例如,C99实现可能具有32位 长的 和64位 long long ,并制作 大小(_t) 的别名 无符号long-long .

    即使在C89/C90中,只有当您有一个符合要求的C89/C9实施时,您才可以依赖担保。C99之前的编译器通常在C89/C90标准之上提供扩展——例如,编译器可能支持 长-长 ,可能会 大小(_t) 的别名 无符号long-long ,即使编译器不完全支持C99(或C11)标准。

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

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

    具有未定义的行为,除非 大小(_t) 恰好是的别名 无符号长 (即使 大小(_t) 无符号长 恰好具有相同的尺寸)。您需要将值强制转换为正确的类型:

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

    对于C99和更高版本,您可以打印 大小(_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年的标准。)