使用线程构建一个简单的计算器

Build a simple calculator using threads

我正在尝试使用C语言中的线程构建一个简单的计算器,代码如下..

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
 
typedef struct Calc {
    int a,b;
}C;

void *add(void* arg) {
    C* temp = (Calc *)arg;
    int ans= temp->a + temp->b;
    printf("Sum is %d\n",ans);
    return NULL;
}
void *sub(void* arg) {
    C* temp = (Calc *)arg;
    int ans= temp->a - temp->b;
    printf("Sub is %d\n",ans);
    return NULL;
}
void *mul(void* arg) {
    C* temp = (Calc *)arg;
    int ans= temp->a * temp->b;
    printf("mul is %d\n",ans);
    return NULL;
} 
void *div(void* arg) {
    C* temp = (Calc *)arg;
    int ans= temp->a / temp->b;
    printf("div is %d\n",ans);
    return NULL;
}

int main() {
    pthread_t t1, t2, t3, t4;
    C* calc = (Calc *)malloc(sizeof(C));    
    calc->a = 7;
    calc->b = 4;
    pthread_create(&t1,NULL,add(calc),NULL);
    pthread_create(&t2,NULL,sub(calc),NULL);
    pthread_create(&t3,NULL,mul(calc),NULL);
    pthread_create(&t4,NULL,div(calc),NULL);
    return 0;
}

我每次调用 Ex.. 函数时都会出错

argument of type "void *" is incompatible with parameter of type "void *(*)(void *)"
40    |     pthread_create(&t2,NULL,sub(calc),NULL);
      |                             ~~~^~~~~~
      |                                |
      |                                void*

谁能告诉我错误是什么以及如何解决?

谢谢你:)

大致总结评论:

首先,线程对于这类程序来说绝对是矫枉过正,但是从某个地方开始学习是好的。

确定一个标识符用于您的结构类型(对 Calc 的引用应为 Cstruct Calc)。

就是说,没有必要将 void * 显式转换为另一种指针类型 - 它在赋值期间被隐式且安全地处理。例如,

C *temp = arg;

C *calc = malloc(sizeof *calc);

两者都很好用,是首选。

C 是一个非常糟糕的类型标识符;尝试一些更具可读性的东西。


这里

pthread_create(&t1, NULL, add(calc), NULL);

您正在尝试调用 add(本身参数类型不正确),并将该函数的结果作为第三个参数传递给 pthread_create

pthread_create 需要一个带有签名 void *(*)(void *) 函数指针 作为它的第三个参数。该函数用作线程的入口点;也称为 start routine.

第四个参数应该是一个void *,它是传递给线程启动例程的指针。


您的线程可能无法在程序的 main 函数退出之前完成执行。要等待线程完成,您可以使用 pthread_join,它将线程作为其第一个参数,并将 void ** 作为其第二个参数 - 一个存储指针的位置而不是 return从线程的启动例程(或更具体地说,pthread_exit 函数)编辑。

pthread_join(t1, NULL);

此函数将阻止调用线程 的执行,直到指定的线程完成。如果指定的线程已经完成,pthread_join return 立即。


这是您程序的最小版本,只有一个 add 线程需要关注。请注意,在此示例中,动态分配内存在很大程度上是不必要的。

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

typedef struct {
    int a;
    int b;
} Calculator;

void *add(void *arg) {
    Calculator *temp = arg;
    int ans = temp->a + temp->b;

    printf("Sum is %d\n", ans);

    return NULL;
}

int main(void) {
    pthread_t t1; /* ...and so on */
    Calculator calc = { .a = 7, .b = 4 };

    pthread_create(&t1, NULL, add, &calc);
    /* ...and so on */

    pthread_join(t1, NULL);
    /* ...and so on */
}

只需复制 pthread_createpthread_join 函数,使用不同的线程并启动例程来扩展它。请注意,如果您想要并发,对 pthread_create 的所有调用都应在对 pthread_join 的任何调用之前发生。


请注意,pthread_createpthread_join 都使用它们的 return 值来表示成功或失败(0 表示成功,否则为错误编号)。

最好检查这些值是否有错误(使用 strerror 获取可打印的字符串)。


更多附录:

  • int main() 实际上应该是 int main(void),或 int main(int argc, char **argv(或等价物)。
  • 标准库中有一个 div 函数。为避免冲突,您需要使用不同的名称。