c89:将int转换为void *并返回

时间:2011-08-12 15:22:38

标签: c c89

首先,这不是一个骗局:

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 ......

4 个答案:

答案 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);