【问题标题】:Variadic function and arbitrary argument saving for future execution可变参数函数和任意参数保存以供将来执行
【发布时间】:2014-02-25 21:00:11
【问题描述】:

我正在用 c 语言开发一个线程池,我想让一个任务有任意数量的参数。甚至认为我可以使用像

这样的功能
int (*task) ();

可以使用任何类型的参数调用此函数,例如我可以这样做

int fib(int n) { return n < 2 ? n : fib(n-1) + fib(n-2); }
...
task = fib;
printf("fib(10)=%d\n",task(10));

但是我想要的是能够保存参数以便以后运行它,而不必使用对 malloc 的调用,因为否则我宁愿只使用类似的任务

void * (*task) (void *);

我只需要将 void * 参数保存在结构上。 但是我想对任意参数执行此操作,是否可以为我想要的任何类型的函数自动生成它,甚至不使用任何 va_list。

有可能吗?

提前发送

【问题讨论】:

  • 我能想到两种解决方案,但都涉及额外的结构或函数。
  • @GradyPlayer 这是一个解决方案的一部分,但你不能单独使用它来“保存”参数。
  • 如果我使用 va_list 我会比只使用分配在堆栈上的结构更糟糕。 (甚至认为它们是宏,它们需要一个 for)
  • 顺便说一句,在 c++ 中我认为这是可能的:cplusplus.com/articles/EhvU7k9E

标签: c asynchronous variadic-functions


【解决方案1】:

恐怕你想要的东西是不可能的——因为我正确理解了你的问题。

我实现它的方式是使用指向struct 的匿名指针,回调和调用者都知道该实现,但线程池不知道,线程池只会携带一个指针。

但是,遗憾的是,该解决方案意味着使用malloc(),或在可能位于堆栈或全局的预分配空间上使用讨厌的内存副本。

【讨论】:

  • 是的,在我当前的实现中,我使用了结构并只保留了一个指向该结构的 void * 指针。实际上,在某些情况下,我可以将结构保存在堆栈中,只需声明它即可。我的问题是线程池需要很快(真的很快)。因此,即使在堆上声明,我也需要初始化结构,因此,我会浪费时间,因为我可以(也许在另一种语言上)简单地用正确的参数调用它。不过谢谢(我暂时不标记为正确,只是为了有更多的答案,请不要误会我的意思,只是这太重要了)。
  • @guilhermemtr 如果您想稍后使用它们,您无法避免将参数复制到额外的内存中。
  • 我的问题是在 cilk(由 mit 制作的多线程语言,现在由 intel 继续)中,他们有一个编译器,所以他们可以很容易地做到这一点。而且我想做到这一点,这样每个应用程序都可以很容易地移植到我的线程池中。 (当我谈到初始化它时,我想说他们只需要复制值然后加载到函数中)。
  • @self,(对您的第一条评论)这实际上是我要提出的观点......对于 OP,好吧,您的另一个选择是我正在告诉的讨厌的解决方案,这是在堆栈中预分配一些内存并用你的结构填充它。您可以使用您允许在回调中使用的不同结构的联合来做到这一点。唯一的事情是,确保您的分配永远超出分配的空间。
  • 好吧,我想这就是他们设计这种语言的原因之一,“Cilk 背后的理念是程序员应该专注于构建程序以暴露并行性并利用局部性......”.. . 因此,他们还为可变参数函数参数进行了更简单的设计。
【解决方案2】:

如果只是参数,那么我会使用:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
typedef void *(*task_t)();
#pragma GCC diagnostic pop

但这不适用于返回类型。

第一个#pragma 让GCC 记住在命令行上提供了哪些-W 标志。当前的警告标志被压入堆栈。

第二个#pragma 让 GCC 不会抱怨没有参数。

第三个#pragma 恢复旧警告。

“#pragma”指令是 C 标准指定的方法,用于向编译器提供超出语言本身传达的信息的附加信息。

  — https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html

【讨论】:

  • 我不熟悉编译指示。我会了解它并尽快提供反馈。不过谢谢
  • 我添加了更多信息。随意询问是否有任何不清楚的地方。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 2010-12-24
  • 2018-10-02
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
相关资源
最近更新 更多