因为我们只能将指针强制转换为另一个指针,所以"(void *)t和(int)threadid"正在使用以下代码? 我们不应该使用& t而不是t?
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
答案 0 :(得分:1)
为了扩展我的评论,C明确规定指针可以转换为整数,反之亦然。除了值为0
的整数常量(可靠地转换为NULL指针)之外,结果是实现定义的。这种转换只能按照我在下面的附录中所述进行可逆转。
然而,实际上,对于某些 n ,指针表示通常采用等效于 n -bit无符号整数的形式。在这些情况下,通常情况下,您可以安全地在指针和足够宽度的整数之间来回转换而不会丢失信息。更有可能(但仍然不能保证)你可以从(不太宽)整数到指针和向后往返而不会丢失信息,即使你可能无法安全地做指针 - &gt;整数 - &gt;指针。符合C的实现将记录所有实现定义的行为的详细信息,包括这些行为。
您提供的计划取决于此类转化;它们可以在许多环境中工作,但它们实际上是否依赖于使用中的C实现。如您所建议的那样,通过传递真正的指针(并将其用作一个)来避免这种实现依赖性。
已更新以添加:
在评论中,@ IanAbbott提出了intptr_t
类型,C2011以这种方式描述:
带符号的整数类型,具有任何有效指针的属性 void可以转换为这种类型,然后转换回指针 void,结果将等于原始指针[...]可选。
- C2011,7.20.1.4
提供此类型的符合实现将确保其关于转换的行为是指定的,但因为它是实现提供它的可选项,所以这与指针/整数转换的实现指定性质不冲突(这在C2011 6.3.2.3/3-6中有描述。因此,即使是提供此类型的实现也不会对涉及其他整数类型(或其他指针类型)的转换承担任何义务。
另请注意,虽然intptr_t
或uintptr_t
(如果可用)提供从指针到整数的往返转换回指针,但它的规定对指针返回整数没有影响,因为就标准而言。
答案 1 :(得分:0)
下面,
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
最后一个参数中的强制转换long
(t
)强制转换为void *
(这是传递给线程函数的参数)。演员表已完成,因为pthread_create()
接受void *
作为最后一个参数。
此值再次从long
转换回void *
值:
tid = (long)threadid;
但是这种转换完全是实现定义的,并且可能被允许成为陷阱表示(因此 undefined )。所以这种转换并不安全。
您可以使用临时数组:
long arr[NUM_THREADS];
for(t=0;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
arr[t] = t;
rc = pthread_create(&threads[t], NULL, PrintHello, &arr[t]);
...
但这涉及确保在线程接收值之前数组arr
的生命周期没有结束。这可以使用主线程中的pthread_join()
或使用malloc
ed指针(而不是使用本地数组arr
)或使用具有静态存储持续时间的数组来完成,例如使{{1}全球。