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

c89:将int转换为void*并返回,c,c89,C,C89,首先,这不是一个骗局: 问题的不同之处在于:我只使用void*来存储int,但实际上我从未将其用作void* 因此,问题实际上归结为: 是否保证空*至少与int一样宽 我不能使用intptr\t,因为我使用的是c89/ANSI C 编辑 在C99(gcc版本)的stdint.h中,我看到了以下内容: /* Types for `void *' pointers. */ #if __WORDSIZE == 64 # ifndef __intptr_t_defined typedef long

首先,这不是一个骗局:

问题的不同之处在于:我只使用void*来存储int,但实际上我从未将其用作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都是从类型定义到整体类型…

不,这不能保证安全

C99标准规定(第6.3.2.3节):

整数可以转换为任何指针类型。除非之前另有规定,否则 结果是定义了实现,可能未正确对齐,可能未指向 引用类型的实体,并且可能是陷阱表示形式

任何指针类型都可以转换为整数类型。除非之前另有规定,否则 结果是定义了实现。如果结果不能用整数类型表示, 该行为未定义。结果不必在任何整数的值范围内 类型

我很有信心,C99之前的版本不会有任何不同。

有一个问题


最清楚的答案是:不,这不安全,避免它,继续下去。但是
POSIX
要求这是可能的。因此,它在兼容POSIX的系统上是安全的。

这里有一个便携式替代方案

static const char dummy[MAX_VALUE_NEEDED];
void *p = (void *)(dummy+i); /* cast to remove the const qualifier */
int i = p-dummy;

当然,如果您需要大的值,它可能会浪费大量的虚拟地址空间,但如果您只想传递小的整数,那么将整数值存储在
void*

中是一种100%可移植且干净的方法,FreeRTOS将计时器ID存储在timer\t中作为void*pvTimerID。因此,当将其用作存储空间而不是指向某个对象的指针时,有必要将其转换为可以用作数组索引的对象,例如

因此,要读取存储为void*的id:


void*pvId=pxTimer->pvTimerID;
int索引=(int)(pvId-NULL);

为什么需要将
int
存储在
void*
中?@Oli Charlesworth:我想构建一个灵活的数组“类”,它可以处理指向对象的指针和int等原始内在类型。我想尝试使用一个并集来强制获得足够的存储空间,但问题是演员可能会以意想不到的方式把事情搞砸。我知道我可以在现代x86上使用它,但我希望它是可移植的。什么铸造?你说的是联合体{int i;void*p;}?@Oli Charlesworth:在内部,我可能有一个联合体,但接口类似于int appendData(void*data);为什么不存储数据并用
void*
指向它?在
void*
中存储某些内容几乎没有意义。POSIX在哪里需要它?我找不到该段落。有人告诉我,所以我可能错了。没关系,我相信这是正确的。我只是对这在实践中出现的地方感兴趣。@Oli Charlesworth我见过一些著名的文本(包括TLPI)将
void*
中的整数作为pthread函数的参数传递给pthread函数。我不认为POSIX明确要求它工作,但POSIX需要(
mmap
),等等一种内存模型,编译器必须恶意破坏所需的强制转换语义。我想,它也会极大地扩大可执行文件的大小。它的默认初始化为零,因此只有坏掉的编译器才会将其存储在可执行文件中;一个合适的会使用bss或者更好的只读bss,如果有这样的东西的话。我很好奇“除非之前指定”部分。我试着寻找一些相关的东西,但几分钟后就找不到了…@Robert:整数常量0转换为空指针常量就在前面,这可能是你的盲点。