是否可以从 C 中的数组调用函数?

Is it possible to call functions from arrays in C?

当我制作我的终端时,我想知道我是否可以通过数组调用一个函数。 (此代码尚未完成,请代码有点乱。)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <unistd.h>
#include <limits.h>
#define true 1
#define false 0
typedef int bool;

/* Static */
static char Input[CHAR_MAX];
static char CurrentDirectory[CHAR_MAX];
static char *Command;
static char *Argument;
static char *Commands[]={"test","test2"};

/* Functions */
int Check_Command();
int test();
int test2();
/* --------- */

int main(){
    printf("#######################\n\tterminal\n\tType \"help\" for the list of commands\n#######################\n");
    prompt:
    printf(">");
    fgets(Input,CHAR_MAX,stdin);
    int res=Check_Command();
    if(res==0){printf("Unknown Command!\n");}
    goto prompt;
}
/* Check_Command() function returns 0 if doesn't suceed and returns 1 of it suceeds */
int Check_Command(){
    //Since input variable is static, no need to send in arguments
    Input[strcspn(Input,"\r\n")]=0;
    Command=strtok(Input," ");
    Argument=strtok(NULL," ");
    int x=0;
    while(x<sizeof(Commands)){
        if(strcmp(Command,Commands[x])==0){
            Commands[x](); <----- Can I call a function like this?
            return 1;
        }
        x++;
    }
    return 0;
}

/* Commands */
int test(){
    printf("Success!\n");
    getchar();
    exit(0);
}

int test2(){
    print("Success [2] \n");
    getchar();
    exit(0);
}

如果可能的话,这将被点亮,我懒得将命令变成可执行文件并为所有命令使用 if 语句。 如果你懒得阅读这里的整个代码是一个基本概念(未测试):

static *Commands[]={"test","test2"};
int main(){
    char *Command="test";
    int x=0;
    while(x<sizeof(Commands)){
        if(strcmp(Command,Commands)==0){
            Commands[x]();
        }
        x++
    }
}
int test(){
   printf("Hi");
}
int test2(){
    printf("hey");
}

编辑:

static char Commands[]={test,test2}; DOES NOT WORK This also includes the "possible duplicate" answer. (Im using Mingw, Windows 10)

您似乎希望能够从用户那里接收一个字符串,例如 test2,然后调用函数 test2()。有两种主要方法可以解决此问题:

  1. 自制结构将名称映射到函数指针。
  2. 使用 'dynamic library loading' 和函数名称解析。

结构数组

首先,您定义一个结构,例如:

struct FuncName
{
    const char *name;
    int (*function)(void);
};

然后您可以定义一个数组:

struct FuncName functions[] =
{
    { "test",  test  },
    { "test2", test2 },
};
enum { NUM_FUNCTIONS = sizeof(functions) / sizeof(functions[0]) };

当你从用户那里得到一个名字时,你可以搜索名字数组并找到匹配的函数指针来调用。

int invoke_function(const char *name)
{
    for (int i = 0; i < NUM_FUNCTIONS; i++)
    {
        if (strcmp(name, functions[i].name) == 0)
        {
            return (*functions[i].function)();
            // Or just: return functions[i].function();
        }
    }
    return -1;   // No match found
}

这在所有系统上都能可靠地工作,但缺点是您必须在编译程序时创建 table 函数指针。

动态库

替代方法是在 Unix (POSIX) 系统上使用 <dlsym.h> header 中的函数 dlopen() and dlsym(),或 Windows 上的等效函数。

通常,您希望在使用 dlopen() 加载的动态加载库中找到函数,但通常有一种方法可以在主执行程序 table 中搜索名称(传递一个空指针作为POSIX 系统上 dlopen() 的文件名)。然后可以调用dlsym()获取指定名称对应的函数指针,调用即可。

void *dlh = dlopen(NULL, RTLD_NOW);

int (*funcptr)(void) = (int (*)(void))dlsym("test", dlh);

return (*funcptr)();

这省略了错误检查,您需要强制转换从 object 指针 (void *) 转换为函数指针,因为 C 标准不要求这样做是可行的,但是 POSIX 确实(见规范 dlsym() 已经链接到)。

Non-uniform 函数签名

对于这两种解决方案,如果所有可调用函数都具有相同的接口,那么生活就很容易了。如果不同的函数有不同的接口,生活就会变得更加混乱(所以有些人不希望有参数,有些人希望有一个,有些人希望有两个,并且参数的类型因函数而异, return 类型也是如此)。期望使用大量强制转换并准备好让编译器提交 - 将代码与其他所有内容隔离开,以便将 non-portable 部分与主要代码分开。

注意:没有向编译器咨询任何此代码的有效性!