This question is almost a duplicate of some others I've found, but this specifically concerns POSIX, and a very common example in pthreads that I've encountered several times. I'm mostly concerned with the current state of affairs (i.e., C99 and POSIX.1-2008 or later), but any interesting historical information is of course interesting as well.
The question basically boils down to whether b will always take the same value as a in the following code:
long int a = /* some valid value */
void *ptr = (void *)a;
long int b = (long int)ptr;
I am aware that this usually works, but the question is whether it is a proper thing to do (i.e., does the C99 and/or POSIX standards guarantee that it will work).
When it comes to C99 it seems it does not, we have 6.3.2.3:
5 An integer may be converted to any pointer type. Except as
previously speci?ed, the result is implementation-de?ned, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.56)
6 Any pointer type may be
converted to an integer type. Except as previously speci?ed, the
result is implementation-de?ned. If the result cannot be represented
in the integer type, the behavior is unde?ned. The result need not be
in the range of values of any integer type.
Even using intptr_t the standard seems to only guarantee that any valid void* can be converted to intptr_t and back again, but it does not guarantee that any intptr_t can be converted to void* and back again.
However it is still possible that the POSIX standard allows this.
I have no great desire to use a void* as a storage space for any variable (I find it pretty ugly even if POSIX should allow it), but I feel I have to ask because of the common example use of the pthreads_create function where the argument to start_routine is an integer, and it is passed in as void* and converted to int or long int in the start_routine function. For example this manpage has such an example (see link for full code):
//Last argument casts int to void *
pthread_create(&tid[i], NULL, sleeping, (void *)SLEEP_TIME);
/* ... */
void * sleeping(void *arg){
//Casting void * back to int
int sleep_time = (int)arg;
/* ... */
}
I've also seen a similar example in a textbook (An Introduction to Parallel Programming by Peter S. Pacheco). Considering that it seems to be a common example used by people who should know this stuff much better than me, I'm wondering if I'm wrong and this is actually a safe and portable thing to be doing.
See Question&Answers more detail:
os