C 为什么我不能将一个void*转换回int*并取消对它的引用?
我试图从我的老师那里了解C语言中的线程,这就是他让我们在课堂上做的方式C 为什么我不能将一个void*转换回int*并取消对它的引用?,c,multithreading,pthreads,C,Multithreading,Pthreads,我试图从我的老师那里了解C语言中的线程,这就是他让我们在课堂上做的方式 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <pthread.h> #define numberlen 1000000 int sum = 0; int arr[numberlen]; void* Summing(void* param) { int n = *((int*)p
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define numberlen 1000000
int sum = 0;
int arr[numberlen];
void* Summing(void* param)
{
int n = *((int*)param); //I'm guessing this is where my issue is but I'm still a first year so i'm not sure.
int base = 500000 * n;
for(int i =0; i<500000;i++)
{
sum += arr[i+base];
}
}
int main()
{
int nonthreadsum = 0;
pthread_t thread_id_first;
pthread_t thread_id_second;
srand(time(NULL));
for(int i = 0; i<numberlen;i++)
{
int r = (rand() % 10);
arr[i] = r;
nonthreadsum += r;
}
printf("%d\n",nonthreadsum);
pthread_create(&thread_id_first, NULL, Summing, (void*)0);
pthread_create(&thread_id_second, NULL, Summing, (void*)1);
printf("%d\n", sum);
return 1;
}
#包括
#包括
#包括
#包括
#定义数字1000000
整数和=0;
int arr[数字];
无效*求和(无效*参数)
{
int n=*((int*)param);//我猜这就是我的问题所在,但我还是第一年,所以我不确定。
整数基数=500000*n;
对于(int i=0;i,允许(在某些情况下)从整数转换为指针,从指针转换为整数。问题在于,这不是您试图做的
调用pthread\u create
时,将整数值1
和0
强制转换为键入void*
。这很好。但在线程函数中执行以下操作:
int n = *((int*)param);
您将void*
参数强制转换为int*
,然后尝试取消对该指针的引用。但是您没有传入int*
。您传入了int
。因此,您的程序将值1和0视为指针(后者实际上是空指针)
由于将值传递给函数时已从int
转换为void*
,因此需要在函数内部转换回int
int n = (int)param;
也就是说,处理此问题的最佳方法是将实际的int*
传递给函数并将其转换回函数中。从int*
转换为void*
并返回在所有情况下都有很好的定义
可以通过在main
函数中定义变量来动态创建内存来保存这些值:
int *t1_val = malloc(sizeof(*t1_val));
int *t2_val = malloc(sizeof(*t2_val));
*t1_val = 0;
*t2_val = 1;
pthread_create(&thread_id_first, NULL, Summing, t1_val);
pthread_create(&thread_id_second, NULL, Summing, t2_val);
然后像以前一样在线程中使用它们,添加对free
的调用:
int n = *((int*)param);
free(param);
通过使用int
类型的变量并传递它们的地址,也可以在不进行动态分配的情况下执行此操作,但您需要确保在线程尝试取消引用指针时,这些变量不会超出范围。将数据的地址传递给线程
将数据的地址传递给线程。不要在指针内传递数据
向线程传递数据的预期方法是传递指向该线程的指针。例如,要传递类型为type
的数据,可以使用:
Type x;
// … Set desired value(s) in x.
pthread_create(&thread_id_first, NULL, Summing, &x);
您可以传递(void*)&x,但无需传递。对于声明为typevoid*
的参数,到void*
的转换将在C中自动进行
然后,在线程中,您应该恢复指针类型:
void *Summing(void *param)
{
Type *p = param;
Type x = *p;
// … Use x.
}
指针从void*
(Type*p=param;
)的转换和指针的使用(Type x=*p;
)在上面的两行中显示以供说明。但是,您可以将它们组合成一行:Type x=*(Type*)param;
为什么使用void*
任何类型的数据都可以通过地址传递给线程。但是,C没有很好的规定可以将任何类型的指针传递给例程。pthread\u create
必须用特定的指针类型声明。void*
用作指针的通用类型。因此pthread\u create
有一个void*
参数,但可以将任何类型的指针传递给对象
在您的情况下,类型可以是int
,替换上面示例代码中的type
。给定int x;
,&x
将是指向int
,int*
的指针。当您将其传递给pthread\u create
时,它将自动转换为void*
然后,在线程中,您需要将其转换回int*
。执行此操作后,您可以访问它指向的int
传递大量数据
线程通常传递的数据多于简单的int
。类型可以是对象类型。通常使用结构。程序将定义结构,例如:
struct foo
{
int start;
int end;
double coefficient;
double ReferenceData[30];
}
与Type
示例一样,可以创建所需类型的对象struct foo x;
,用数据填充它,然后将&x
传递给pthread\u create
。然后线程将接收到的void*
转换为struct foo*
,并使用它访问数据
在本例中,由于数据太多,线程可能不想复制它,这就是struct foo x=*(struct foo*)param;
可以。相反,线程可能只是创建一个正确类型的指针,struct foo*p=param;
。然后线程可以通过->
操作符使用数据:p->start
,p->ReferenceData[i]
,等等
线程还可以通过将结果放入指向的数据中,以这种方式将结果传递回其创建者
只传递一点数据
要传递少量数据,有一个快捷方式:您可以创建一个对象并使用复合文字传递其地址:
pthread_create(&thread_id_first, NULL, Summing, & (int) {1});`.
这将创建一个值为1的int
对象,并将其地址传递给pthread\u create
。然后线程将使用int x=*(int*)参数获得int
通常,代码结构(type){initial values}
称为复合文字。它创建一个具有类型type和给定初始值的对象。&
获取其地址
复合文字具有自动存储持续时间,因此&(int){1}
将只存在(为其保留内存),直到创建它的例程的执行结束。在线程使用复合文字完成之前,不应让该例程结束
如果您需要一个对象比创建线程的例程的执行时间更长,则可以使用malloc
为数据保留内存。很抱歉,我实际尝试了此操作,但遇到编译错误Threads。c:13:14:警告:从pointe强制转换