在几个C ++示例中,我看到使用size_t类型,我将使用一个简单的int。有什么区别,为什么size_t会更好?
答案 0 :(得分:135)
stdlib.h和stddef.h头文件定义了一种名为 size_t 的数据类型,用于表示对象的大小。采用大小的库函数期望它们的类型为size_t,而sizeof运算符的计算结果为size_t。
size_t的实际类型取决于平台;一个常见的错误是假设size_t与unsigned int相同,这可能导致编程错误,特别是当64位架构变得更加普遍时。
另外,请检查Why size_t matters
答案 1 :(得分:28)
size_t是用于表示大小的类型(顾名思义)。它的平台(甚至可能的实现)依赖,并且只应用于此目的。显然,表示大小,size_t是无符号的。许多stdlib函数,包括malloc,sizeof和各种字符串操作函数都使用size_t作为数据类型。
默认情况下会对int进行签名,即使它的大小也依赖于平台,它在大多数现代机器上都是固定的32位(虽然size_t在64位架构上是64位,但int仍然在这些架构上保持32位长)。
总结:在其他情况下,使用size_t表示对象的大小和int(或long)。
答案 2 :(得分:7)
这是因为size_t可以是除int之外的任何东西(可能是结构)。这个想法是它将它的工作与基础类型分离开来。
答案 3 :(得分:6)
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位指令集); Motorola 68000有一个带有32位寄存器和地址的16位ALU; IBM主机有15位,24位或31位地址。您还可以在嵌入式系统中看到不同的ALU和地址总线大小。
任何时候int
小于size_t
,并且您尝试在unsigned int
中存储非常大的文件或对象的大小或偏移量,它可能会溢出并导致错误。使用int
,也有可能获得负数。如果int
或unsigned int
更宽,程序将正常运行但浪费内存。
如果您想要便携性,通常应该使用正确的类型。很多人会建议您使用带符号的数学而不是无符号(以避免令人讨厌的,像1U < -3
这样的微妙错误)。为此,标准库将ptrdiff_t
中的<stddef.h>
定义为从另一个指针中减去指针的结果的有符号类型。
也就是说,解决方法可能是边界检查 - INT_MAX
以及0
或INT_MIN
的所有地址和抵消情况,并打开编译器有关比较签名和如果您错过任何未签名的数量。无论如何,您应始终始终检查数组访问是否存在溢出。
答案 4 :(得分:0)
SIZE_T
的定义见:
https://msdn.microsoft.com/en-us/library/cc441980.aspx和https://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;