我有一个数组( C语言)应该在编译时初始化。
例如:
DECLARE_CMD(f1, arg); DECLARE_CMD(f2, arg);
从多个文件中调用DECLARE_CMD。
我想要对它进行预处理。
my_func_type my_funcs [] = { &f1, &f2 }
使用宏可以将项附加到静态数组?
我在gcc4上使用C99(带GNU扩展)。
注意:在您的问题中,每行末尾都有分号。 这将严重干扰任何使用这些宏的尝试。 所以这取决于找到DECLARE_CMD(...)
行的位置和方式,以及是否可以修复分号问题。 如果它们只是一个专用的头文件,你可以这样做:
#define DECLARE_CMD(func, arg) &func, my_func_type my_funcs [] { #include "file_with_declare_cmd.h" };
……变成了:
my_func_type my_funcs [] { &f1, &f2, };
阅读新C:X宏以获得对此的详细解释。
如果你无法摆脱分号,这将被处理为:
my_func_type my_funcs [] { &f1,; &f2,; };
…这显然是语法错误,所以这不起作用。
是的,你可以在编译时(而不是在运行时)构建动态数组(感谢Mitchel Humpherys),我们的想法是在同一部分声明你的回调,如下所示:
例:
假设你有三个文件ac,bc main.c和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, }
进入交流
#include "ih" static void f1(void) { .... } ADD_FUNC(f1);
进入公元前
#include "ih" static void f2(void) { .... } ADD_FUNC(f2);
进入main.c
#include "ih" 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; }
重要
有时编译器会优化开始/结束部分变量,它会将它们清除掉,因此当您尝试使用它们时,您将遇到链接器错误: 错误LNK2019:未解析的外部符号…
要解决此问题,我使用以下内容:
复制两者之间的文字:
==================================================
在一个文件(例如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 = .;
对的,这是可能的。 通常的技巧是将所有DECLARE_CMD(func, args)
行包含在一个(或多个)包含文件中,并将这些行包含在具有宏的适当定义的各个位置。
例如:
在’commands.inc’文件中:
DECLARE_CMD(f1, args) DECLARE_CMD(f2, args)
在一些源文件中:
/* 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 };
您实际上可以使用单个宏来设置函数指针,执行函数声明,设置枚举以访问函数指针和用于错误消息的字符串,稍后您可以在switch()
使用它。
#define X_MACRO(OP) OP(addi, int x, int y) OP(divi, int x, int y) OP(muli, int x, int y) OP(subi, int x, int y) #define AS_FUNC_PTR(x,...) x, #define AS_FUNC(x,...) int x(__VA_ARGS__); #define AS_STRINGS(x,...) #x, #define AS_ENUMS(x,...) ENUM_##x, X_MACRO(AS_FUNC) typedef int (*foo_ptr_t)( int, int ); foo_ptr_t foo[] = { X_MACRO(AS_FUNC_PTR) }; char *foo_strings[] = { X_MACRO(AS_STRINGS) }; enum foo_enums { X_MACRO(AS_ENUMS) }; /** example switch() #define AS_CASE(x,...) ENUM_x : x(i,j);break; switch (my_foo_enum){ X_MACRO(AS_CASE) default: do_error(); } **/
以上就是c/c++开发分享使用宏将项目附加到具有宏的数组中相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/544816.html