c - 在 C 中使用宏将项目附加到数组

标签 c arrays initialization c-preprocessor

我有一个数组(C 语言)应该在编译时初始化。

例如:

DECLARE_CMD(f1, arg);
DECLARE_CMD(f2, arg);

DECLARE_CMD 从多个文件调用。

我希望对其进行预处理。

my_func_type my_funcs [] = {
   &f1,
   &f2
}

可以使用宏将项目附加到静态数组吗?

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

最佳答案

是的,您可以在编译时(而不是在运行时)构建动态数组(感谢 Mitchel Humpherys),想法是像这样在同一部分中声明您的回调:

示例:

假设你有三个文件 a.c, b.c main.c 和 i.h

进入 i.h

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,                           \
    }

进入空调

#include "i.h"

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

ADD_FUNC(f1);

进入 b.c

#include "i.h"

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

ADD_FUNC(f2);

进入main.c

 #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: unresolved external symbol ...

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

  1. 尝试打印您的链接描述文件:

    gcc -Wl,-详细

复制两者之间的文字:

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

在一个文件中(例如 lnk.lds),您应该看到如下内容:

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

OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64","elf64-x86-64")

........

  1. 将您的部分添加到链接描述文件 lnk.lds 在 .data 部分之后,如下所示(我定义的部分在示例中称为 my_array):
  __start_my_array = .;
  .my_array :
  {
    *(.my_array)      
  }
  __stop_my_array = .;
  1. 像这样使用更新后的链接描述文件编译您的程序:

    gcc -O3 -Xlinker -T"lnk.lds"file.c -o 程序

  2. 如果你输入字符串程序| grep "__start_my_array" 你应该找到它。

关于c - 在 C 中使用宏将项目附加到数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3633896/

相关文章:

arrays - Snowflake - 如何将单个字段(VARIANT)拆分为多个列

ruby - 有没有办法通过散列来初始化对象?

c++ - 这个 Actor 分配了什么? C风格选角

c - C语言编程中使用结构体时出现错误

javascript - 如何将数组元素组合成一个新数组?

C char 数组 v C char* 初始化

c++ - 使用类设置 win32 应用程序的更好方法?

c - 如何在编译时链接Libb64库?

c - 错误 c2400 发现新行

c - 在 C 中将 char* 反序列化为结构体