C语言引入头文件时自动调用register_printf_function注册函数的方法问询
C语言自定义printf处理器自动注册实现方案
- 实现原理:利用编译器提供的「构造函数」特性,让指定函数在程序
main函数执行前、或者动态库加载时自动运行,无需用户手动调用注册逻辑。 - 常规带源文件模块的实现方式
你把注册逻辑放在模块的.c源文件中即可,只要项目链接了你的模块,注册逻辑会自动执行,无需用户在引入头文件后做额外操作:
// widget.c 新增代码 #include "widget.h" #include <printf.h> // 构造函数属性标记,程序启动时自动执行 static __attribute__((constructor)) void widget_printf_auto_reg(void) { // 加判断避免重复注册 static int is_reg = 0; if (is_reg) return; register_printf_function ('W', print_widget, print_widget_arginfo); is_reg = 1; }
- 头文件-only模块的实现方式
如果你的模块只有头文件,直接把上述逻辑写到widget.h的头文件守卫内即可,每个引入头文件的编译单元都会自动生成注册逻辑,配合静态标记不会重复执行:
// widget.h 核心代码 #ifndef WIDGET_H #define WIDGET_H #include <printf.h> // 你的自定义printf处理函数声明 int print_widget(FILE *stream, const struct printf_info *info, const void *const *args); int print_widget_arginfo(const struct printf_info *info, size_t n, int *argtypes, int *size); static __attribute__((constructor)) void widget_printf_auto_reg(void) { static int is_reg = 0; if (is_reg) return; register_printf_function ('W', print_widget, print_widget_arginfo); is_reg = 1; } #endif
- 兼容性说明
- 上述
__attribute__((constructor))语法兼容GCC、Clang、MinGW编译器 - 若需要兼容MSVC,可使用MSVC专用的初始化段语法实现同等效果:
#ifdef _MSC_VER #pragma section(".CRT$XCU", read) static void __cdecl widget_printf_auto_reg(void); __declspec(allocate(".CRT$XCU")) void (__cdecl *reg_ptr)(void) = widget_printf_auto_reg; static void __cdecl widget_printf_auto_reg(void) { static int is_reg = 0; if (is_reg) return; register_printf_function ('W', print_widget, print_widget_arginfo); is_reg = 1; } #else // 前述GCC兼容的构造函数实现 #endif - 注意
register_printf_function本身是GNU C扩展,不属于C标准,仅在glibc环境下可用。
- 上述
内容的提问来源于stack exchange,提问作者Jerico
相关产品推荐
相关产品推荐

