c89: Convert an int to void* and back

2019-04-27 12:18发布

First off, this is not a dupe of:

Is it safe to cast an int to void pointer and back to int again?

The difference in the questions is this: I'm only using the void* to store the int, but I never actually use it as a void*.

So the question really comes down to this:

Is a void * guaranteed to be at least as wide as an int

I can't use intptr_t because I'm using c89 / ANSI C.

EDIT

In stdint.h from C99 ( gcc version ) I see the following:

/* 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

Could I possibly just jerry rig something similar and expect it to work? It would seem that the casting should work as all intptr_t is is a typedef to an integral type...

标签: c c89
4条回答
孤傲高冷的网名
2楼-- · 2019-04-27 12:35

FreeRTOS stores timer IDs in Timer_t as void* pvTimerID. So when using this as a storage space, and NOT a pointer to something, it is necessary to cast it to something that can be used as an array index, for instance.

so to read the id, stored as a void*:

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

查看更多
forever°为你锁心
3楼-- · 2019-04-27 12:39

There is a C FAQ: Can I temporarily stuff an integer into a pointer, or vice versa? .

The cleanest answer is: no, this is not safe, avoid it and get on with it. But POSIX requires this to be possible. So it is safe on POSIX-compliant systems.

查看更多
贪生不怕死
4楼-- · 2019-04-27 12:40

No, this is not guaranteed to be safe.

The C99 standard has this to say (section 6.3.2.3):

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

I'm pretty confident that pre-C99 won't be any different.

查看更多
太酷不给撩
5楼-- · 2019-04-27 12:41

Here's a portable alternative.

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

Of course it can waste prohibitively large amounts of virtual address space if you need large values, but if you just want to pass small integers, it's a 100% portable and clean way to store integer values in void *.

查看更多
登录 后发表回答