size_t与uintptr_t
C标准保证size_t
是一个可以容纳任何数组索引的types。 这意味着,在逻辑上, size_t
应该能够保存任何指针types。 我在Google上发现的一些网站上说,这是合法的和/或应该始终工作:
void *v = malloc(10); size_t s = (size_t) v;
那么在C99中,标准引入了intptr_t
和uintptr_t
types,它们是有符号和无符号types,保证能够保存指针:
uintptr_t p = (size_t) v;
那么使用size_t
和uintptr_t
什么区别呢? 两者都是无符号的,都应该能够容纳任何指针types,所以它们在function上看起来是一样的。 除了清晰度之外,有没有真正有说服力的理由使用uintptr_t
(或更好的是void *
)而不是size_t
? 在一个不透明的结构中,这个领域只能由内部function来处理,是否有理由不这样做?
同样的道理, ptrdiff_t
是一个能够保存指针差异的签名types,因此能够保存大多数指针,所以它与intptr_t
有什么不同呢?
并不是所有这些types基本上服务于相同function的普通不同版本? 如果没有,为什么? 我不能用其中一个做我不能用另一个做的事情? 如果是这样的话,为什么C99在语言中增加了两个基本多余的types?
我愿意忽视函数指针,因为它们不适用于当前的问题,但随意提及它们,因为我怀疑它们是“正确”答案的核心。
size_t是一个可以容纳任何数组索引的types。 这意味着,在逻辑上,size_t应该能够保存任何指针types
不必要! 回头看看分段的16位体系结构的时代,例如:一个数组可能被限制在一个单独的段(所以16位size_t
会这样做),但是你可能有多个段(所以需要一个32位的intptr_t
types挑选段以及它内的偏移量)。 我知道在这些统一可寻址的非分段架构中这些东西听起来很奇怪,但标准必须迎合“2009年正常情况”这样的多种types,你知道的!)
关于你的陈述:
“C标准保证了
size_t
是一个可以容纳任何数组索引的types,这意味着在逻辑上,size_t
应该能够保存任何指针types。
这被称为谬误,是由错误推理导致的误解。 你可能会认为后者来自前者,但并不一定如此。
指针和数组索引不是一回事。 设想一个将数组限制为65536个元素的一致性实现是相当合理的,但是允许指针将任何值写入一个大量的128位地址空间。
C99指出, size_t
variables的上限是由SIZE_MAX
定义的,并且可以低至65535(参见C99 TR3,7.18.3,在C11中保持不变)。 如果指针在现代系统中被限制在这个范围内,指针将是相当有限的。
在实践中,你可能会发现你的假设是成立的,但这不是因为这个标准能够保证。 因为它实际上不能保证它。
我会让所有其他的答案代表段的限制,异国build筑,等等的理由。
名称的理由不是简单的差异,足以使用正确的types适当的东西?
如果您要存储大小,请使用size_t
。 如果你正在存储一个指针,使用intptr_t
。 读取你的代码的人会立即知道“aha,这是一个大小的东西,可能以字节为单位”,“哦,这是一个指针值存储为整数,出于某种原因”。
否则,你可以使用unsigned long
(或者,在这里这些现代, unsigned long long
)的一切。 大小不是一切,types名称带有意义,这是有用的,因为它有助于描述程序。
最大数组的大小可能比指针小。 考虑分段体系结构 – 指针可能是32位,但是一个段可能只能处理64KB(例如旧的实模式8086体系结构)。
虽然这些在桌面机器中不常用,但C标准旨在支持甚至是小型的专用体系结构。 例如,仍然有8位或16位CPU开发的embedded式系统。
我会想象(这适用于所有types的名称),它更好地expression了你的代码意图。
例如,即使unsigned short
和wchar_t
在Windows上的大小相同(我认为),但使用wchar_t
而不是unsigned short
表示您将使用它来存储一个宽字符,而不是一些任意数字。
回头看看,回想起各种各样的古怪的build筑风格,我很确定他们试图包装所有现有的系统,并提供所有可能的未来系统。
可以肯定的是,事情解决的方式,我们迄今为止不需要太多的types。
但是,即使在LP64这个相当常见的范例中,我们也需要size_t和ssize_t作为系统调用接口。 人们可以想象一个更受限制的遗留系统或将来的系统,其中使用完整的64位types是昂贵的,他们可能想要投入大于4GB的I / O操作,但仍然具有64位指针。
我想你不得不怀疑:可能发展了什么,未来会发生什么。 (也许是128位的分布式系统互联网范围内的指针,但是在系统调用中不超过64位,或者甚至是“遗留的”32位限制。:-)图像遗留系统可能获得新的C编译器。 。
另外,看看那里存在的东西。 除了2800个实模式的内存模块之外,CDC的60位/ 18位指针大型机怎么样? Cray系列怎么样? 不要介意正常的ILP64,LP64,LLP64。 (我一直认为微软有LLP64的优势,应该是P64)。我当然可以想象一个委员会试图覆盖所有的基地。
int main(){ int a[4]={0,1,5,3}; int a0 = a[0]; int a1 = *(a+1); int a2 = *(2+a); int a3 = 3[a]; return a2; }
暗示intptr_t必须总是替代size_t,反之亦然。