Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么我不能将一个void*转换回int*并取消对它的引用?_C_Multithreading_Pthreads - Fatal编程技术网

C 为什么我不能将一个void*转换回int*并取消对它的引用?

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

我试图从我的老师那里了解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*)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,但无需传递。对于声明为type
void*
的参数,到
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强制转换