intptr_t有什么用?

我知道它是一个整数类型,可以在不丢失数据的情况下强制转换为指针,但为什么我要这样做呢? 有一个整数类型有什么优势可以使用void*来保存指针而使用THE_REAL_TYPE*进行指针运算?

编辑
标记为“已经被问到”的问题没有回答这个问题。 问题是如果使用intptr_t作为void*的一般替换是一个好主意,那里的答案似乎是“不要使用intptr_t”,所以我的问题仍然有效:什么是intptr_t一个很好的用例?

主要原因是,你不能对void *进行按位运算,但是你可以在intptr_t上做同样的操作。

在许多场合,您需要对地址执行按位操作,您可以使用intptr_t

但是,对于按位运算,最好的方法是使用unsigned对应的uintptr_t

正如@chux在另一个答案中所提到的 ,指针比较是另一个重要方面。

另外,FWIW,根据C11标准,§7.20.1.4,

这些类型是可选的。

intptr_t有什么用?

使用示例:订单比较。
比较指向相等的指针不是问题。
其他比较操作,如>, <=可能是UB。 C11dr§6.5.8/ 5关系运算符。
所以首先转换为intptr_t

[编辑]新示例:按指针值对指针数组进行排序。

 int ptr_cmp(const void *a, const void *b) { intptr_t ia = (intptr) (*((void **) a)); intptr_t ib = (intptr) (*((void **) b)); return (ia > ib) - (ia < ib); } void *a[N]; ... qsort(a, sizeof a/sizeof a[0], sizeof a[0], ptr_cmp); 

[原实例]使用示例:测试指针是否为指针数组。

 #define N 10 char special[N][1]; // UB as testing order of pointer, not of the same array, is UB. int test_special1(char *candidate) { return (candidate >= special[0]) && (candidate <= special[N-1]); } // OK - integer compare int test_special2(char *candidate) { intptr_t ca = (intptr_t) candidate; intptr_t mn = (intptr_t) special[0]; intptr_t mx = (intptr_t) special[N-1]; return (ca >= mn) && (ca <= mx); } 

如@MM评论,上述代码可能无法按预期工作。 但至少它不是UB。 - 只是非便携式function。 我希望用它来解决这个问题 。

在编写内存管理代码时,uintptr_t类型非常有用。 这种代码希望通过通用指针(void *)与客户端进行通信,但内部对地址进行各种算术运算。

你可以通过char *而不是所有的东西来做同样的事情,结果看起来像前Ansi C.

并非所有内存管理代码都使用uintptr_t – 例如,BSD内核代码定义了具有类似属性的vm_offset_t。 但是,如果您正在编写一个调试malloc包,为什么要创建自己的类型呢?

当你的printf中有%p可用时,它也很有用,并且正在编写需要在各种体系结构上以hex格式打印指针大小的整数变量的代码。

我发现intptr_t相当不太有用,除了可能在转换时作为一个方式站,以避免在同一个强制转换中改变签名和整数大小的恐惧警告。 (编写在所有相关体系结构上传递-Wall -Werror的可移植代码可能会有点费力。)

还有一个语义考虑因素。

void*应该指向某种东西 。 尽管具有现代实用性,但指针不是存储器地址。 好吧,它通常/可能/总是(!)拥有一个,但它不是一个数字。 这是一个指针。 它指的是一件事。

intptr_t没有。 它是一个整数值,可以安全地转换为指针/从指针转换,因此您可以将它用于古老的API,将其打包成pthread函数参数,就像这样。

这就是为什么你可以在intptr_t上做的事情比你在void*上做的更多,以及为什么你应该通过使用适当的类型来自我记录。

最终,几乎所有东西都可以是整数(记住,你的计算机可以处理数字!)。 指针可能是整数。 但他们不是。 它们是指针,因为它们用于不同的用途。 而且,从理论上讲,它们可能不是数字。