这个问题几乎与我发现的其他一些问题相同,但这个问题特别涉及POSIX,这是我在pthreads中遇到的一个非常常见的例子.我主要关注当前的事态(即C99和POSIX.1-2008或更高版本),但任何有趣的历史信息当然也很有趣.
问题基本上归结为b是否总是采用与以下代码中的a相同的值:
long int a = /* some valid value */
void *ptr = (void *)a;
long int b = (long int)ptr;
Run Code Online (Sandbox Code Playgroud)
我知道这通常有效,但问题是它是否是正确的事情(即,C99和/或POSIX标准是否保证它能够正常工作).
说到C99,它似乎没有,我们有6.3.2.3:
5整数可以转换为任何指针类型.除了之前指定的,结果是实现定义,可能没有正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示.56)
6任何指针类型都可以转换为整数类型.除了之前指定的,结果是实现定义.如果结果无法以整数类型表示,则行为未定义.结果不必在任何整数类型的值范围内.
即使使用intptr_t,标准似乎只能保证任何有效的void*都可以转换为intptr_t并再次返回,但它不能保证任何intptr_t都可以转换为void*并再次返回.
但是,POSIX标准仍然可以允许这样做.
我没有很大的愿望使用void*作为任何变量的存储空间(即使POSIX应该允许它我觉得它很难看),但我觉得我必须要问因为pthreads_create函数的常用示例使用了start_routine的参数是一个整数,它作为void*传入,并在start_routine函数中转换为int或long int.例如,此联机帮助页有这样的示例(请参阅完整代码的链接):
//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;
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
我也在教科书(Peter S. Pacheco的并行编程简介)中看到了类似的例子.考虑到它似乎是一个常见的例子,人们应该比我更了解这些东西,我想知道我是否错了,这实际上是一个安全和便携的事情.