gpt4 book ai didi

c - 计算在C语言中使用哪个函数(或某种代码)

转载 作者:太空宇宙 更新时间:2023-11-04 00:14:54 24 4
gpt4 key购买 nike

我有一个不寻常的问题假设我有很多函数:

void function1(){ //some code here }
void function2(){ //some code here }
...
void functionN(){ //some code here }

有没有办法,我可以计算或找出动态,哪个函数使用,没有IF语句根据函数名的名称,调用它?
让我给你看看伪代码,它可以更好地描述情况:
 for(int I=1;I<=N;I++){
functionI();
}

我的意思是,如果有可能计算(例如在char数组中,但也可以通过其他方式)某种代码,我稍后将插入并使用。但不是字符串,而是直接像代码一样让我用不同的例子演示一下:
int num=3;
char functionInString[]="printf(num);
//Some code, that would for example change letters in
functionInString, for example to different fuction
consisting of letters

//And here, do whatever is written in functionToString

对不起,如果我说得不够清楚有人能告诉我,如果用C语言,或者其他语言,这个概念是如何被称为的吗?

最佳答案

您可能需要了解closures和callbacks是什么Function pointers很有用,但单独使用可能还不够(请阅读更多内容,了解函数指针对实现闭包是如何有用的)。
你应该学习更多关于C的知识,所以读一些关于C编程的好书。我建议下载C11标准n1570并浏览一下。一个非常重要的概念是undefined behavior,你应该scared
如果有可能计算(例如在char数组中,但也可以通过其他方式)某种代码,我稍后将插入并使用但不是字符串,而是直接像代码一样
这在纯标准C代码中是不可能的(因为包含程序的translation units的集合是固定的),原则上任何有效的函数指针值都应该指向某个现有函数(所以严格的SSENU调用任何其他函数指针值将是未定义的行为)。然而,有些实现能够(以某种特定于实现的方式)以某种方式构造“有效”的新函数指针(但这超出了C11标准)在纯代码位于ROM中的Harvard architectures上,这甚至是不可能的。
生成并动态加载插件
但是,如果您使用的是现代的operating system(我推荐使用Linux),那么您可能会使用dynamic loadingplugin工具。我特别关注Linux(对于Windows,细节是非常不同的,邪恶就在细节中;请阅读Levine的书Linkers and Loaders)。阅读Operating Systems: Three Easy Pieces了解有关操作系统的更多信息。
所以(在Linux上)可以做的是在运行时在一些临时文件中生成一些C代码,比如/tmp/generated.c;您需要定义关于该文件的约定(比如,它定义了一个void pluginfun(int)函数,该函数具有一些其他需要的属性);然后您使用一个编译命令将其编译成一个共享对象(Drepper读取How to write shared libraries),也就是说一个插件。因此,您的程序可能运行(可能使用system(3),或者使用fork(2)execve(2)waitpid(2)等低级系统调用)编译过程,例如gcc -Wall -O -fPIC /tmp/generated.c -shared -o /tmp/generatedplugin.so;稍后,您的主程序将使用dlopen(3)加载该插件:

void* dlh = dlopen("/tmp/generatedplugin.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "dlopen /tmp/generatedplugin.so failed: %s\n",
dlerror());
exit(EXIT_FAILURE);
}

因为您关心函数指针,所以如果您将它们的签名声明为类型,那么您的代码将更具可读性:
typedef void pluginfun_type(int);

然后很容易声明指向该签名函数的函数指针:
pluginfun_type* fptr = NULL; 

你的程序可以在你的插件中使用 dlsym(3)pluginfun函数地址:
fptr = (pluginfun_type*) dlsym(dlh, "pluginfun");
if (!fptr) {
fprintf(stderr, "dlsym of pluginfun failed: %s\n", dlerror());
exit(EXIT_FAILURE);
}

最后使用 (*fptr)(3)调用该函数。
您应该使用 gcc -O -Wall foo.o bar.o -rdynamic -ldl -o foobarprog链接主程序您可以最后调用 dlclose(3),但如果插件中某个函数的某些调用帧仍处于活动状态,则不应该这样做。
这种生成插件的方法在Linux上非常有效My manydl.c是一个生成“随机”C代码的玩具程序,将生成的C代码编译成生成的插件,然后加载该插件(并且可以重复多次)它表明,在实践中,一个Linux程序可以生成和加载数十万(如果你足够耐心的话,甚至可能是数百万)插件实际上, code segments泄漏是可以接受的(并且可以通过小心使用 dlclose来避免)
今天电脑很快你可以在每个 REPL交互中生成一个小插件(少于1000行C),编译并加载它(对于这样一个小插件,通常需要不到0.1秒),这实际上与人类交互兼容(我在我过时的 GCC MELT项目中这样做了;我将在报告草稿中描述的 bismon项目中这样做。
使用JIT编译库
要在运行时动态生成代码,还可以使用一些 bismon-chariot-doc.pdf库其中有很多,包括 JIT-compilation、AA>(C++)、 libgccjitLLVM、GNU asmjitlibjit及其 libtcc。其中一些能够快速地发出机器代码,但是代码的性能可能不是很好。另一种是像一个好的C编译器那样进行优化(特别是使用内部 lightningtinycc)当然,这些优化需要一些时间,因此机器代码的发送速度非常慢,但其性能与优化的C代码一样好。
嵌入解释器
在许多情况下,脚本语言提供某种 libgccjit有几个解释器被设计成可以很容易地嵌入到您的应用程序中(带有警告和警告),特别是 GCCeval(和 Lua)。更多的解释器(Ocaml、Python、Perl、Parrot、Ruby,…)也可以以某种方式嵌入到您的应用程序中(您可能需要理解 Guile术语)。当然,所有这些都需要一些编码约定。实际上,解释器比编译的代码慢。
术语
有人能告诉我,如果用C语言,或者其他语言,这个概念是如何被称为的吗?
你可能需要阅读更多关于 Nimgarbage collectionmetaprogrammingevalmultistage programminghomoiconicityreflectioncontinuationstype introspection(考虑伊恩·泰勒的 stack trace)。
你可能对类似于 libbacktrace的语言感兴趣。先读一读,然后是奎内克的书和斯科特的书。注意 Lisp(一个常见的Lisp实现)正在每个REPL交互中生成机器代码。
既然你提到了对人工智能的兴趣,你可以研究一下 SICP。他的CAIA系统是 Lisp In Small Pieces所以生成了它的C代码的总数(大约500公里)。

关于c - 计算在C语言中使用哪个函数(或某种代码),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53549982/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com