【问题标题】:Passing Array as argument to a new thread in C将数组作为参数传递给 C 中的新线程
【发布时间】:2014-02-25 01:53:35
【问题描述】:

我正在尝试使用 pthread_create 将数组作为参数传递给新线程中的函数,这可能吗?我有一个整数数组和一个从创建线程方法调用的计算平均值方法,但我似乎无法正确地将我的数组传递给该方法。这是我的代码: 整数 [];

int average;

int size = 0;


void *calcAvg(int *nums[]);

int main(int argc, char *argv[]){
    /* initialize an array of the integers to be passed */
    nums[argc - 1];
    for(int i = 0; i < argc - 1; i++){
        nums[i] = atoi(argv[i + 1]);
        size++;
    }

    /* Thread Identifier */
    pthread_t avgThread;

    pthread_create(&avgThread, NULL, calcAvg, nums);

    pthread_join(avgThread, NULL);

    printf("average= %d", average);
}

void *calcAvg(int *nums[]){
    int sum;
    for(int i = 0; i < size; i++){
        sum += nums[i];
    }
    average = sum / (size);
    pthread_exit(0);
}

【问题讨论】:

  • 这还能编译吗? nums in main 似乎没有正确声明。
  • 您应该真正确定您是否遇到了编译时、链接时或运行时问题。显示的代码不应该在没有警告的情况下编译;如果是,您需要提高编译的警告级别。你应该修复警告;请记住,C 编译器可能比您更了解 C。
  • 线程的函数应该有签名void *thread_function(void *arg)——一个接受“通用指针”(指向void的指针)作为参数并返回指向void的指针的函数。您的calcAvg() 函数与此不匹配,因此michaeltang 的解决方案解决了该问题。最后没有特别的理由使用pthread_exit(0);;如果它是我的代码,我会使用 return 0; — 但最终结果是相同的,只是编译器不会抱怨没有从应该这样做的函数返回值。
  • 在函数中,从 void *int * 的转换是合法的,因为输入最初是一个 int 数组,它首先被转换为一个 int 指针(指向数组的第一个元素),然后指向 void 指针以匹配函数原型。您使用int *nums[] 的声明设法使用了两级指针,其中只需要一个;使用int *numsint nums[] 会做得更好——在函数声明或定义中使用时会有等价的(但仅在该上下文中——在其他地方,它们是相当不同的)。
  • 剩下的问题是样式问题——和线程安全问题。您使用两个全局变量sizeaverage。鉴于您的主线程在唯一的子线程正在执行时进入睡眠状态,所以没有问题。如果您有两个或更多子线程,则需要担心使用变量是否安全。鉴于size 在线程启动后就已修复(因此他们只会读取它),那么就可以了。但是,如果多个线程正在访问average,您确实需要一个互斥锁或类似的东西来保护它免受并发访问。

标签: c arrays multithreading


【解决方案1】:

你的代码有很多问题,我修复了一些来编译 希望对你有帮助

编译:gcc -o main main.c -lpthread

执行:./main 2 5

输出:3

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

int average;

int size = 0;


void *calcAvg(void *arg);
int main(int argc, char *argv[]){
  /* initialize an array of the integers to be passed */
  int *nums = (int*)malloc((argc - 1)*sizeof(int));
  int i = 1;
  for(i = 1; i < argc ; i++){
    nums[i-1] = atoi(argv[i]);
    size++;
  }

  /* Thread Identifier */
  pthread_t avgThread;

  pthread_create(&avgThread, NULL, calcAvg, (void*)nums);

  pthread_join(avgThread, NULL);
  printf("average = %d \n",average);
  free(nums);

}
void *calcAvg(void *arg){
  int *val_p = (int *) arg;
  int sum = 0;
  int i = 0;
  for( i = 0; i < size; i++){
    sum += val_p[i];
  }
  average = sum / (size);
  pthread_exit(0);
}

【讨论】:

  • 问题标记为 C,而不是 C++,所以从技术上讲,您应该使用 gcc 而不是 g++ 进行编译。您还应该使用 VLA(正如原始代码试图做的那样)或 malloc() 或范围检查和静态数组,而不是使用 new
  • 谢谢,所以你必须将数组转换为 void 类型?我仍然对 C 中的 * 究竟做了什么感到困惑。因此,您将数组转换为 void 类型,而 * 与将其声明为指针有关,您能详细说明一下吗?谢谢!
  • 最好的做法是将事物转换为 void 类型,然后在传递 args 时将它们转换回来?
  • @justinhenricks ,当函数用作线程的回调函数时需要,您可以将nums视为int的指针。它认为您应该阅读书中*的含义和用法
  • 这是针对特定问题的解决方案,不回答提出的问题。也许这对 OP 有所帮助,但我认为这对社区中的其他任何人都没有用。恕我直言,这个答案应该被删除或修改。
【解决方案2】:

更改以下内容

void *calcAvg(int *nums[]){
    int sum;
    for(int i = 0; i < size; i++){
        sum += nums[i];
    }
    average = sum / (size);
    pthread_exit(0);
}

void *calcAvg(void *arg){
    int *val_p = (int *) arg;
    int sum;
    for(int i = 0; i < size; i++){
        sum += val_p[i];
    }
    average = sum / (size);
    pthread_exit(0);
}

【讨论】:

    【解决方案3】:

    'pthread_create()' 的主要问题是将 void 指针作为其最后一个参数。您正试图将一个指向整数的指针数组传递给它。在终端发出“man pthread_create”以查看您应该传递的参数类型。

    你真正想做的只是将数组整数传递给线程。在 C 中,数组索引只是指针算术的符号。写nums[i] 等同于&amp;nums[0] + i 或只是nums+i。最后一种情况有效,因为 C 中的数组名称可以用作指向数组第一个元素的指针。

    void *calcAvg(int *nums[]) 更改为void *calcAvg(void* thread_args)。然后在'calcAvg'中写int *nums = (int*)thread_args。现在您可以在该函数中使用nums,就像您调用了calcAvg(nums)一样,实际上您已经完成了。

    【讨论】:

    • 给定范围内的原型,编译器将在调用中自动将int * 转换为void *。事实上,这不应该引起编译器的警告。应该引起警告的是将void (*func)(int *) 函数指针传递给期望void (*func)(void *) 的例程。
    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2014-11-14
    • 2016-10-05
    • 2013-10-29
    • 2022-11-25
    • 2012-06-25
    相关资源
    最近更新 更多