【问题标题】:What's the difference between size_t and int in C++?C++ 中的 size_t 和 int 有什么区别?
【发布时间】:2010-10-04 21:49:33
【问题描述】:

在几个 C++ 示例中,我看到了 size_t 类型的使用,而我会使用简单的 int。有什么区别,为什么size_t 应该更好?

【问题讨论】:

标签: c++ c types int


【解决方案1】:

size_t 类型定义为sizeof 运算符的无符号整数类型。在现实世界中,您经常会看到 int 定义为 32 位(为了向后兼容),但 size_t 在 64 位平台上定义为 64 位(因此您可以声明大小超过 4 GiB 的数组和结构)。如果 long int 也是 64 位的,这称为 LP64 约定;如果 long int 是 32 位但 long long int 和指针是 64 位,那就是 LLP64。您也可能得到相反的结果,该程序使用 64 位指令来提高速度,但使用 32 位指针来节省内存。此外,int 已签名,size_t 未签名。

从历史上看,有许多其他平台的地址比int 的原始大小更宽或更短。事实上,在 70 年代和 80 年代初期,这种情况比较普遍:所有流行的 8 位微机都有 8 位寄存器和 16 位地址,而 16 位和 32 位之间的转换也产生了许多机器地址比他们的寄存器更宽。我偶尔还会在这里看到有关用于 MS-DOS 的 Borland Turbo C 的问题,它的巨大内存模式在 16 位 CPU 上以 32 位存储 20 位地址(但它可以支持 80386 的 32 位指令集);摩托罗拉 68000 有一个 16 位 ALU,带有 32 位寄存器和地址;有 15 位、24 位或 31 位地址的 IBM 大型机。您还可以在嵌入式系统中看到不同的 ALU 和地址总线大小。

任何时候int 小于size_t,并且您尝试将非常大的文件或对象的大小或偏移量存储在unsigned int 中,它可能会溢出并导致错误。使用int,也有可能得到一个负数。如果intunsigned int 更宽,程序将正常运行但会浪费内存。

如果您想要可移植性,您通常应该使用正确的类型。很多人会建议您使用有符号数学而不是无符号数学(以避免像1U < -3 这样的讨厌的、微妙的错误)。为此,标准库将<stddef.h> 中的ptrdiff_t 定义为从另一个指针中减去一个指针的结果的有符号类型。

也就是说,一种解决方法可能是根据INT_MAX0INT_MIN 对所有地址和偏移量进行边界检查,并在您错过时打开有关比较有符号和无符号数量的编译器警告任何。无论如何,您应该始终、始终、始终检查您的数组访问是否存在溢出。

【讨论】:

    【解决方案2】:

    SIZE_T 的定义位于: https://msdn.microsoft.com/en-us/library/cc441980.aspxhttps://msdn.microsoft.com/en-us/library/cc230394.aspx

    在此处粘贴所需信息:

    SIZE_T 是一个ULONG_PTR,表示指针可以指向的最大字节数。

    该类型声明如下:

    typedef ULONG_PTR SIZE_T;
    

    ULONG_PTR 是用于指针精度的无符号长类型。它用于将指针转换为 long 类型以执行指针运算。

    该类型声明如下:

    typedef unsigned __int3264 ULONG_PTR;
    

    【讨论】:

    • SIZE_T 不是 size_t,OP 询问的内容。
    • 这是微软的扩展,不是标准语言的一部分。
    • SIZE_Tsize_t 完全不同。您不能声明SIZE_T 类型的变量。
    【解决方案3】:

    来自the friendly Wikipedia

    stdlib.h 和 stddef.h 头文件定义了一个名为 size_t 的数据类型,用于表示对象的大小。采用 size 的库函数期望它们是 size_t 类型,并且 sizeof 运算符的计算结果为 size_t。

    size_t 的实际类型取决于平台;一个常见的错误是假设 size_t 与 unsigned int 相同,这可能导致编程错误,尤其是在 64 位架构变得越来越普遍的情况下。

    另外,请检查Why size_t matters

    【讨论】:

    • 那么,size_t 是什么?
    • @NDEthos 这取决于!在这里,Linux /usr/include/stdlib.h/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h 获取定义,其中默认为 long unsigned int,除非其他头文件另有说明。
    • 我确认size_t to int tuncation is dangerous。这可能是题外话,但是当这种错误在linux内核中发生数千次时,如何单独编写一个补丁来修复这种错误呢?
    【解决方案4】:

    size_t 是用于表示尺寸的类型(顾名思义)。它依赖于平台(甚至可能是实现),并且应该仅用于此目的。显然,表示一个大小,size_t 是无符号的。许多 stdlib 函数,包括 malloc、sizeof 和各种字符串操作函数都使用 size_t 作为数据类型。

    默认情况下,int 已签名,尽管它的大小也取决于平台,但在大多数现代机器上它将是固定的 32 位(虽然 size_t 在 64 位架构上是 64 位,但 int 在那些架构上保持 32 位长) )。

    总结一下:使用 size_t 表示对象的大小,在其他情况下使用 int(或 long)。

    【讨论】:

      【解决方案5】:

      这是因为 size_t 可以是除 int 以外的任何东西(可能是结构)。这个想法是将其工作与底层类型分离。

      【讨论】:

      • 我认为 size_t 实际上可以保证是无符号整数的别名,因此它不能是结构。不过,我现在没有方便的参考资料来支持这一点。
      • @danio 为什么会这样?你能解释一下吗?
      • 如果我是你,我不会链接到 cplusplus!如果你不能引用章节、诗句、段落和台词,那一切都只是道听途说! :-)
      • size_t 被指定为 无符号整数 类型。 C11 §6.5.3.4 5“两个运算符的结果值(sizeof_Alignof)是实现定义的,其类型(无符号整数类型)是size_t,”。
      猜你喜欢
      • 1970-01-01
      • 2010-09-12
      • 2012-08-30
      • 2019-09-04
      • 2021-01-05
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多