函数 printHello 以下 接收无效指针 作为参数。 但是这个指针会被转换成很长的代码并且代码可以运行。我不认为我理解这种转换是如何运作的。 Aren的指针类型应该保存地址吗? 如何将long类型突然兼容转换为指针类型,反之亦然?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define NUM_OF_THREADS 5
void *printHello (void *thread_id)
{
long tid;
tid = (long) thread_id; // Why is this possible?
printf("hello from thread #%ld!", tid);
pthread_exit(NULL);
}
int main()
{
pthread_t threads[NUM_OF_THREADS];
int return_code;
long i;
for(i=0; i<NUM_OF_THREADS; i++)
{
printf("In main: creating thread %ld\n", i);
return_code = pthread_create(&threads[i],NULL,printHello,(void*) i);
// Why does it allow to cast 'long i' into '(void*) i'?
if(return_code)
{
printf("Error: return code from pthread_create is %d\n", return_code);
exit(-1);
}
}
pthread_exit(NULL);
}
示例输出:
In main: creating thread 0
In main: creating thread 1
hello from thread #0!
hello from thread #1!
In main: creating thread 2
In main: creating thread 3
hello from thread #2!
In main: creating thread 4
hello from thread #3!
hello from thread #4!
答案 0 :(得分:3)
整数可以转换为任何指针类型,任何指针类型都可以转换为整数类型,因为语言标准是这样说的。地址和整数都是固定长度的位集合,因此没有什么不可能的。
这种转换的结果是实现定义的,但它在实践中往往很有效。标准备注&#34;映射函数将指针转换为整数或整数转换为指针,旨在与执行环境的寻址结构保持一致&#34;。
除非有一些不寻常的表示,如果两种类型的数据位数相同,则转换应该双向工作。该标准指定指针可以转换为intptr_t
或uintptr_t
并再次返回,这实际上通常意味着这些类型至少与指针一样大。许多旧代码使用long
用于相同目的。似乎无法保证另一方向的往返安全,这是该计划所需要的。它通常有用。
答案 1 :(得分:1)
(void*) i
您对编译器撒谎,使其认为i
是一个地址。迫使演员总是做点什么。并不意味着它的推荐。
它有用(只要您不尝试取消引用该值),因为void *
具有相同的大小或大于long
,但它肯定是实现的定义,应该避免。
您应该将指针传递给您的数据(因为您的变量在main
中声明且具有兼容的范围,所以它没有问题)
return_code = pthread_create(&threads[i],NULL,printHello,&i);
并在您的线程代码中取消引用它:
void *printHello (void *thread_id)
{
long tid = *((long *)thread_id);
}