coj*_*car 6 c arrays initialization c-preprocessor
我有一个数组(C语言),应在编译时初始化。
例如:
DECLARE_CMD(f1, arg);
DECLARE_CMD(f2, arg);
Run Code Online (Sandbox Code Playgroud)
从多个文件中调用DECLARE_CMD。
我希望对此进行预处理。
my_func_type my_funcs [] = {
&f1,
&f2
}
Run Code Online (Sandbox Code Playgroud)
是否可以通过宏将项目附加到静态数组?
我在gcc4上使用C99(具有GNU扩展名)。
是的,您可以在编译时(而不是在运行时)构建动态数组(感谢 Mitchel Humpherys),其想法是在同一部分声明您的回调,如下所示:
例子:
假设你有三个文件 ac, bc main.c 和 ih
进入 ih
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, \
}
Run Code Online (Sandbox Code Playgroud)
交流
#include "i.h"
static void f1(void) {
....
}
ADD_FUNC(f1);
Run Code Online (Sandbox Code Playgroud)
进入公元前
#include "i.h"
static void f2(void) {
....
}
ADD_FUNC(f2);
Run Code Online (Sandbox Code Playgroud)
进入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;
}
Run Code Online (Sandbox Code Playgroud)
重要的
有时编译器会优化开始/结束部分变量,将它们清除,因此当您尝试使用它们时,您将遇到链接器错误:错误 LNK2019:未解析的外部符号...
为了解决这个问题,我使用以下方法:
尝试打印您的链接器脚本:
gcc -Wl,-详细
复制两者之间的文本:
==================================================
在文件(例如lnk.lds)中,您应该看到如下内容:
/* -z combreloc 的脚本:组合和排序 reloc 部分 */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64","elf64-x86-64")
…………
__start_my_array = .;
.my_array :
{
*(.my_array)
}
__stop_my_array = .;
Run Code Online (Sandbox Code Playgroud)
使用更新后的链接器脚本编译您的程序,如下所示:
gcc -O3 -Xlinker -T"lnk.lds" file.c -o program
如果您键入字符串程序 | grep "__start_my_array"你应该能找到它。
注意:在您的问题中,每行末尾都有分号。这将严重干扰任何使用这些宏的尝试。因此,这取决于在哪里以及如何DECLARE_CMD(...)找到这些行,以及是否可以解决分号问题。如果它们只是单独位于专用头文件中,您可以执行以下操作:
#define DECLARE_CMD(func, arg) &func,
my_func_type my_funcs [] {
#include "file_with_declare_cmd.h"
};
Run Code Online (Sandbox Code Playgroud)
...变成:
my_func_type my_funcs [] {
&f1,
&f2,
};
Run Code Online (Sandbox Code Playgroud)
请阅读新的 C: X 宏以获得对此的详细解释。
如果您无法去掉分号,这将被处理为:
my_func_type my_funcs [] {
&f1,;
&f2,;
};
Run Code Online (Sandbox Code Playgroud)
...这显然是一个语法错误,所以这不起作用。