C标准保证size_t
是一种可以容纳任何数组索引的类型。这意味着,从逻辑上讲,size_t
应该能够容纳任何指针类型。我在谷歌上找到了一些网站,上面写着这是合法的,或者应该总是起作用:
void *v = malloc(10);
size_t s = (size_t) v;
因此,在C99中,标准引入了intptr_t
和uintptr_t
类型,它们是有符号和无符号的类型,保证可以容纳指针:
uintptr_t p = (size_t) v;
那么,使用 size_t
和 uintptr_t
有什么区别?两者都是无符号类型,都应该能够容纳任何指针类型,因此它们在功能上似乎相同。除了清晰度之外,使用 uintptr_t
(或者最好是 void *
) 而不是 size_t
是否有任何真正的强制性理由?在一个不透明的结构中,如果该字段只会被内部函数处理,那么不这样做是否有任何原因呢?同样,
ptrdiff_t
是一种有符号类型,可容纳指针之间的差异,因此可以容纳大多数指针,那么它与 intptr_t
有何不同?所有这些类型岂不是基本上提供了同一功能的微不足道的不同版本吗?如果不是,为什么?我能用其中一个做不了什么我不能用另一个做的事情吗?如果是,为什么 C99 在语言中添加了两个基本上是多余的类型?
我愿意忽略函数指针,因为它们与当前问题无关,但请随意提到它们,因为我有一种隐约的感觉它们将是“正确”答案的核心。
size_t
和uintptr_t
之间的区别。但是ptrdiff_t
和intptr_t
呢?几乎在任何平台上,这两者都能存储相同范围的值,为什么还需要有有符号和无符号的指针大小整数类型,特别是如果ptrdiff_t
已经用作有符号指针大小整数类型的话。 - Chris Lutzsize_t
至少为16位,但ptrdiff_t
至少为17位(实际上意味着它可能至少为32位)。 - Keith ThompsonSIZE_MAX
不应该是2的64次方。需要注意的是,这里采用的是平面地址寻址方式;即没有必要使用分段来使SIZE_MAX
与数据指针范围不匹配。 - Andon M. Coleman