1

在我的程序中,调用pthread_create如下所示:

res = pthread_create(&a_thread, NULL, thread_fn, (void*)n);

我的问题是,为什么我们不能做到:

res = pthread_create(&a_thread, NULL, thread_fn( (void*)n) );

因为这将减少参数的数量pthread_create并且看起来也合乎逻辑,至于函数我只学到了 3 件事:声明、定义和调用。

将函数名称作为参数传递并添加到将其参数作为单独的参数传递是我不明白的事情。

如果这种格式背后有任何逻辑,请解释。

4

3 回答 3

8

最明显的论点是您不能调用thread_fn“作为参数”,因为它需要在被调用之前 pthread_create运行到完成——也就是说,您将在当前线程中运行发往新线程的代码。

另一种看待事物的方式是,创建执行线程必然会利用操作系统(内核)代码。在新线程变得有效可用之前,操作系统需要设置其内部簿记结构。pthread_create内核调用(例如由) 使用第一种语法完成。

于 2013-09-02T20:35:30.313 回答
1

res = pthread_create(&a_thread, NULL, thread_fn( (void*)n) );

请记住,粗体部分是函数调用。C 语言的语义调用执行该函数调用,然后将其返回值替换为它的位置。所以,这个语法,等价于下面的顺序。

  1. temp = thread_fn( (void*)n) // 函数调用
  2. res = pthread_create(&a_thread, NULL, temp)

这显然不是你想要的。您想要的是函数 pthread_create 首先创建一个单独的执行线程,该线程使用您指定的参数执行函数调用 thread_fn。

以下是 pthread_create 需要做的事情。

  1. 创建一个新的线程执行上下文。
  2. 设置 thread_fn 的调用上下文,即设置堆栈和参数等。
  3. 安排输入 thread_fn。

因为函数 thread_fn 以延迟方式执行,所以唯一的方法是保留函数入口点及其参数,然后安排它执行。这就是为什么将这些作为参数传递给 pthread_create。

于 2013-09-02T21:00:11.317 回答
0

当您将函数作为函数调用的参数调用时,实际发生的是该函数被调用并将return value放在堆栈上以传递给您正在调用的函数。

strthings(getStr1(), strlen(getStr1()), getStr2(), strlen(getStr2()));

转换为(顺序可能因编译器/cpu 而异)

auto t1 = getStr2();   // probably not exact order
auto t2 = strlen(t1);
auto t3 = getStr1();
auto t4 = strlen(t3);
strthings(t3, t4, t1, t2);

所以 - 你的一段代码:

*res = pthread_create   (&a_thread , NULL , thread_fn( (void*)n) )

将转化为

// run the thread function and get the return value.
auto t1 = thread_fn((void*n));
*res = pthread_create(&a_thread, NULL, t1);

我们将在我们的线程上下文中运行 thread_fn,然后传递它的返回值。听起来您希望将函数作为参数传递给被调用函数并内联解释?

为什么传递函数和参数有效?

--- 编辑:解释为什么分别传递函数和参数有效。

在 C 中,函数名实际上是指针变量。指针的类型取决于函数的“指纹”。

int strncmp(const char* left, const char* right, int maxlen);

实际上是

int (*strncmp)(const char*, const char*, int);

也就是说,strncmp 是一个指向函数的指针,该函数返回一个 void 并采用指定类型的三个参数。

这形成了一个合同,所以当你写

int n = strncmp(a, b, 3);

它知道在 [presudo] 程序集中做一些事情,例如:

push a
push b
push 3
call 0x783af83  // strncmp
mov  return -> n
pop  12

所以 - 现在您知道函数实际上是指针(指向代码),您可以了解如何传递它们,以便您可以执行以下操作:

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

int func1() { return 1; }
int func2() { return 22; }

int flip(int useFirst, int (*first)(), int (*second)()) {
    return (useFirst) ? first() : second();
}

int main() {
    srand(time(NULL));
    int useFirst = rand() % 2;
    int result = flip(useFirst, func1, func2);
    printf("use first is %u. return value was %u.\n", useFirst, result);
}
于 2013-09-02T20:41:05.150 回答