【问题标题】:C - accessing variable names in struct values as stringsC - 将结构值中的变量名作为字符串访问
【发布时间】:2021-06-29 14:15:09
【问题描述】:

我有一个结构数组,其中 .act 值不是字符串,而是函数名:

cgi_object_t cgi_machine_learning_handlers[] =
{
{
    .path = "schema",
    .grp = ACC_GRP_ML,  
    .r_vdom = VDOM_PER_VDOM,
    .r_global = VDOM_PER_VDOM,
    .act = cgi_ml_schema,
    .flags = API_FLAG_NO_SCHEMA, 
},
{
    .path = "policy.svmattacktypes",
    .grp = ACC_GRP_ML,  
    .r_vdom = VDOM_PER_VDOM,
    .r_global = VDOM_PER_VDOM,
    .act = cgi_ml_policy_svmattacktypes_get,
    .flags = API_FLAG_NO_SCHEMA, 
}

我正在尝试以字符串的形式访问这些函数名—— cgi_ml_schema 等。有没有办法做到这一点?我尝试在下面使用#,但它抱怨程序中有杂散的'#'。

const char * var = json_object_object_get(request, #(m->act))
response = json_object_object_get(info, #(m->act));

【问题讨论】:

  • 将名称添加为结构中的字段。
  • 是的。有没有我不必这样做的替代方法?直接读取指针名称? @dbush
  • 您可能必须创建一个X macro 才能在此处以可维护的方式添加某种内省。但是,只有在初始化函数指针后从不更改函数指针时,这才有效。

标签: c string struct


【解决方案1】:

您基本上是在询问是否可以从指针本身读取指针的名称。让我们试试吧。你能告诉我地址​​ 0x55c0c6e93190 的函数名称是什么吗?我觉得不是。任何人也不能,除非相应的名称存储在某个地方的内存中。编译后变量名称不再存在(除非您计划利用调试信息)。

但您可以尝试自动存储名称以及指针,如下所示:

#include <stdio.h>

typedef int (*fnptr_t)(int a, int b);

typedef struct named_ptr {
    fnptr_t ptr;
    const char *name;
} named_ptr;

named_ptr make_named_ptr(fnptr_t ptr, const char *name) {
    named_ptr p = {ptr, name};
    return p;
}
#define MAKE_NAMED_PTR(x) make_named_ptr(x, #x)

typedef struct cgi_object_t {
    char *path;
    int grp, r_vdom, r_global;
    named_ptr act;
    int flags; 
} cgi_object_t;

enum dummy {ACC_GRP_ML, VDOM_PER_VDOM, API_FLAG_NO_SCHEMA};
int cgi_ml_schema(int a, int b) { return 0; }
int cgi_ml_policy_svmattacktypes_get(int a, int b) { return 0; }

int main(void) 
{
    cgi_object_t cgi_machine_learning_handlers[] = {
        {
            .path = "schema",
            .grp = ACC_GRP_ML,  
            .r_vdom = VDOM_PER_VDOM,
            .r_global = VDOM_PER_VDOM,
            .act = MAKE_NAMED_PTR(cgi_ml_schema),
            .flags = API_FLAG_NO_SCHEMA, 
        },
        {
            .path = "policy.svmattacktypes",
            .grp = ACC_GRP_ML,  
            .r_vdom = VDOM_PER_VDOM,
            .r_global = VDOM_PER_VDOM,
            .act = MAKE_NAMED_PTR(cgi_ml_policy_svmattacktypes_get),
            .flags = API_FLAG_NO_SCHEMA, 
        }
    };
    
    for (size_t i = 0; i < 2; ++i) {
        cgi_object_t *m = cgi_machine_learning_handlers + i;
        printf("%s is at address %p\n", m->act.name, m->act.ptr);
    }
    
    return 0;
}

我真的猜到并编造了很多东西,但想法就在那里。下次,您应该提供Minimal, Reproducible Example

测试它here

如果您的编译器支持它们,则函数调用可以替换为复合文字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    相关资源
    最近更新 更多