C 标准保证 anint
能够存储每个可能的数组大小。至少,这就是我通过阅读第 6.5.2.1 节第 1 小节(数组下标约束)所理解的:
其中一个表达式应具有类型“指向对象类型的指针”,另一个表达式应具有整数类型,并且结果具有类型“类型”。
既然我们要用int
s 作为数组下标,为什么要用 ssize_t
来确定数组的大小呢?
为什么strlen()
返回size_t
什么时候int
就足够了?
术语“整数类型”并不意味着int
- 例如char
, 并且short
是整数类型。
仅仅因为您可以使用 anint
来为数组下标并不一定意味着它可以到达所有可能的数组元素。
更具体地说,关于size_t
vs.int
的一个例子是平台int
可能是 16 位类型,size_t
也可能是 32 位类型(或者在当今 64 位平台上更常见的 32 位int
与 64 位差异)。size_t
整数类型不一定是“int”。“long long”也是整数类型,“size_t”也是如此。
数组可以大于 2GB。对于那些编写需要大量内存的程序的人来说,这个属性非常方便,例如具有大缓冲池的 DBMS、具有大内存缓存的应用程序服务器等。大于 2GB/4GB 的数组是 64 位计算的重点:)
strlen() 的 size_t,至少听起来与 C 标准处理数组的方式兼容,无论它是否具有实际意义,或者是否有人见过这么大的字符串,都是另一个问题。
首先,您从标准中引用的内容并未int
具体提及类型。不,int
不能保证足以在 C 中存储任何对象(包括数组)的大小。
其次,C 语言实际上并没有专门的“数组订阅”。数组订阅是通过指针算法实现的。并且指针算术中的整数操作数具有ptrdiff_t
类型。不是size_t
,不是int
,而是ptrdiff_t
。它是有符号类型,顺便说一句,这意味着该值可以为负数。
第三, 的目的size_t
是存储程序中任意对象的大小(即存储 的结果sizeof
)。它不会立即用作数组索引。它恰好作为数组索引工作,因为它保证它总是足够大以索引任何数组。但是,从抽象的角度来看,“数组”是一种特定的“容器”,还有其他类型的容器(基于列表的容器、基于树的容器等等)。在一般情况下size_t
不足以存储任何容器的大小,这在一般情况下也使其成为数组索引的一个值得商榷的选择。(strlen
另一方面,是一个专门与数组一起使用的函数,这在size_t
此处很合适。)
在编写 C 标准时,机器通常具有 16 位“int”类型,并且无法处理任何大于 65535 字节的单个对象,但仍能够处理大于 32767 字节的对象。由于无符号整数上的算术足以处理此类对象的最大大小,但有符号整数上的算术不会,因此将 size_t 定义为无符号以便适应此类对象而无需使用“长”计算。
在最大允许对象大小介于 INT_MAX 和 UINT_MAX 之间的机器上,指向此类对象的开始和结束的指针之间的差异可能太大而无法放入“int”。虽然标准没有对实现应该如何处理它施加任何要求,但一种常见的方法是定义整数和指针环绕行为,这样如果 S 和 E 是指向 char[49152] 的开头和结尾的指针,那么即使 ES 会超过 INT_MAX,它也会产生一个值,当它与 S 相加时,将产生 E。
如今,size_t 是无符号类型这一事实很少有任何真正的优势(因为需要大于 2GB 的对象的代码由于其他原因通常需要使用 64 位指针),并且它会导致涉及对象大小的多种比较行为与直觉相反,但 sizeof 表达式产生无符号类型的事实已经根深蒂固,以至于它永远不会改变。
size_t 是无符号整数的 typedef(例如 int 或 long)。
在一些 64 位平台中,int 可以是 32 位,而 size_t 可以是 64 位。
它被用作更标准的尺寸方式。