首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >以C语言将项附加到具有宏的数组中

以C语言将项附加到具有宏的数组中
EN

Stack Overflow用户
提问于 2010-09-03 07:50:29
回答 4查看 6.8K关注 0票数 10

我有一个数组(C language),应该在编译时初始化它。

例如:

代码语言:javascript
复制
DECLARE_CMD(f1, arg);
DECLARE_CMD(f2, arg);

DECLARE_CMD是从多个文件调用的。

我要把这个做预处理。

代码语言:javascript
复制
my_func_type my_funcs [] = {
   &f1,
   &f2
}

是否可以使用宏将项附加到静态数组中?

我在gcc4上使用gcc4(带有GNU扩展)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-09-03 07:58:13

注意:在你的问题中,每一行的末尾都有分号。这将严重干扰使用这些宏的任何尝试。因此,这取决于在哪里和如何找到DECLARE_CMD(...)行,以及您是否能够修复分号问题。如果它们只是单独存在于一个专用的头文件中,您可以这样做:

代码语言:javascript
复制
#define DECLARE_CMD(func, arg) &func,

my_func_type my_funcs [] {
    #include "file_with_declare_cmd.h"
};

...which被转化为:

代码语言:javascript
复制
my_func_type my_funcs [] {
    &f1,
    &f2,
};

请阅读新C: X宏,以获得对此的良好解释。

如果不能去掉分号,将处理如下:

代码语言:javascript
复制
my_func_type my_funcs [] {
    &f1,;
    &f2,;
};

..。这显然是语法错误,所以这是行不通的。

票数 2
EN

Stack Overflow用户

发布于 2016-05-06 22:21:53

是的,您可以在编译时(而不是在运行时)构建动态数组(感谢米切尔·汉弗里斯),其思想是在下面的同一节中声明您的回调:

例子:

假设您有三个文件: a.c、B.C.main.c和i.h。

进入i.h

代码语言:javascript
复制
typedef void (*my_func_cb)(void);

typedef struct func_ptr_s {
       my_func_cb cb; /* function callback */
} func_ptr_t;

#define ADD_FUNC(func_cb)                        \
    static func_ptr_t ptr_##func_cb              \
    __attribute((used, section("my_array"))) = { \
        .cb = func_cb,                           \
    }

转换为a.c

代码语言:javascript
复制
#include "i.h"

static void f1(void) {
   ....
}

ADD_FUNC(f1);

将转换为b.c

代码语言:javascript
复制
#include "i.h"

static void f2(void) {
   ....
}

ADD_FUNC(f2);

将转换为main.c

代码语言:javascript
复制
 #include "i.h"
 
 static void f3(void) {
   ....
 }

 ADD_FUNC(f3);   

 #define section_foreach_entry(section_name, type_t, elem)    \
     for (type_t *elem =                                      \
            ({                                                \
                extern type_t __start_##section_name;         \
                &__start_##section_name;                      \
            });                                               \
            elem !=                                           \
            ({                                                \
                extern type_t __stop_##section_name;          \
                &__stop_##section_name;                       \
            });                                               \
            ++elem)
            

 int main(int argc, char *argv[])
 {
    section_foreach_entry(my_array, func_ptr_t, entry) {
            entry->cb(); /* this will call f1, f2 and f3 */
    }

    return 0;
 }

重要

有时编译器会优化开始/结束部分变量,然后删除它们,所以当您尝试使用它们时,您将有一个链接器错误:error LNK2019:未决外部符号.

要解决这个问题,我使用以下方法:

  1. 尝试打印链接器脚本: gcc -Wl,-verbose

复制两者之间的文本:

==================================================

在一个文件(例如lnk.lds)中,应该是这样的:

用于/* combreloc的-z脚本:合并和排序reloc部分*/

OUTPUT_FORMAT(“elf64 64-x86-64”、“elf64 64-x86-64”、“elf64 64-x86-64”)

.

  1. 将节添加到链接器脚本文件lnk.lds 的.data节之后,如下所示(我定义的部分名为my_array,如本例所示):

代码语言:javascript
复制
  __start_my_array = .;
  .my_array :
  {
    *(.my_array)      
  }
  __stop_my_array = .;

  1. 使用更新的链接器脚本编译程序,如下所示: gcc -O3 -Xlinker -T"lnk.lds“文件c -o程序
  2. 如果您键入字符串程序\ grep "__start_my_array",您应该会找到它。
票数 11
EN

Stack Overflow用户

发布于 2010-09-03 08:05:34

是的,这是可能的。通常的技巧是在一个(或多个)包含文件的一个(或多个)中包含所有的DECLARE_CMD(func, args)行,并在不同的地方包含那些对宏有适当定义的行。

例如:

文件“Commands.inc”中:

代码语言:javascript
复制
DECLARE_CMD(f1, args)
DECLARE_CMD(f2, args)

在某些源文件中:

代码语言:javascript
复制
/* function declarations */
#define DECLARE_CMD(func, args) my_func_type func;
#include "commands.inc"
#undef DECLARE_CMD

/* array with poiners */
#define DECLARE_CMD(func, args) &func,
my_func_type* my_funcs[] = {
    #include "commands.inc"
    NULL
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3633896

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档