C89: Converting int to void * and vice versa

Firstly, this is not a hoax:

Is it possible to include int to remove the pointer and back to int?

The difference in questions is this: I use void * to store int, but I never use it as void *.

So, the question really comes down to the following:

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

I cannot use intptr_t because I am 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 

Can I possibly just install something like this and expect it to work? It would seem that casting should work like all intptr_t is a typedef for an integral type ...

+7
source share
4 answers

No, this is not guaranteed.

The C99 standard says this (section 6.3.2.3):

An integer can be converted to any type of pointer. Except as noted above, the result is determined by the implementation, may not be aligned correctly, may not point to an object of a reference type, and may be a trap representation.

Any type of pointer can be converted to an integer type. Except as noted above, the result is determined by implementation. If the result cannot be represented in an integer type, the behavior is undefined. The result should not be in the range of values โ€‹โ€‹of any integer type.

I am sure that the pre-C99 will not be different.

+9
source

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

The cleanest answer: no, this is unsafe, avoid it and continue with it. But POSIX requires it to be possible. Thus, it is safe for POSIX-compatible systems.

+1
source

Here is 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 exorbitant amounts of virtual address space if you need large values, but if you just want to pass small integers, this is a 100% portable and clean way to store integer values โ€‹โ€‹in void * .

+1
source

FreeRTOS stores timer identifiers in Timer_t as void * pvTimerID. Therefore, when you use this as a storage space, and NOT a pointer to something, you need to attribute it to what can be used as an index of an array, for example.

to read the id saved as void *:

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

+1
source

All Articles