首先,这不是一个骗局:
Is it safe to cast an int to void pointer and back to int again?
问题的不同之处在于:我只使用void *来存储int,但我实际上从未将它用作void *。
所以问题实际上归结为:
void *保证至少与int
一样宽我无法使用intptr_t,因为我使用的是c89 / ANSI C.
修改
在C99(gcc版本)的stdint.h中,我看到以下内容:
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned long int uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned int uintptr_t;
#endif
我是否可能只是对类似的东西进行操作并希望它能够正常工作?似乎转换应该工作,因为所有intptr_t都是一个整数类型的typedef ......
答案 0 :(得分:9)
不,这不能保证安全。
C99标准就是这样说的(第6.3.2.3节):
整数可以转换为任何指针类型。除非事先指明,否则 结果是实现定义的,可能没有正确对齐,可能不指向 引用类型的实体,可能是陷阱表示。
任何指针类型都可以转换为整数类型。除非事先指明,否则 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。结果不必在任何整数的值范围内 类型。
我非常有信心C99之前不会有任何不同。
答案 1 :(得分:1)
有C FAQ: Can I temporarily stuff an integer into a pointer, or vice versa? 。
最干净的答案是:不,这不安全,避免它并继续使用它。但是POSIX
要求这是可能的。所以在符合POSIX标准的系统上是安全的。
答案 2 :(得分:1)
这是一种便携式替代方案。
static const char dummy[MAX_VALUE_NEEDED];
void *p = (void *)(dummy+i); /* cast to remove the const qualifier */
int i = p-dummy;
当然,如果您需要较大的值,它可能会浪费大量的虚拟地址空间,但如果您只想传递小整数,那么这是一种100%便携且干净的方式来存储void *
中的整数值。
答案 3 :(得分:1)
FreeRTOS将Timer_t中的计时器ID存储为void * pvTimerID。因此,当使用它作为存储空间而不是指向某个东西的指针时,有必要将其转换为可用作数组索引的东西,例如。
所以要读取id,存储为void *:
void* pvId = pxTimer->pvTimerID;
int index = (int)(pvId - NULL);