我正在处理一段将用于多个项目的代码,我刚刚意识到如果函数的调用受if保护,我只能使用函数原型(没有实际实现)。 样品:
#ifndef __TEST_H
#define __TEST_H
uint32_t test_init(void);
#if CONFIG_TEST
bool is_test_supported(void);
#else
static inline bool is_test_supported(void)
{
return false;
}
#endif
#endif
在c文件中我有
...
if (is_test_supported())
test_init();
...
在没有定义CONFIG_TEST的系统上,上面的代码仍然可以正常编译。我想这是因为编译器足够聪明,可以理解代码路径永远不会执行,这是正确的,这种行为是否可移植?编译器是clang。
编辑:纠正了函数名称的一些错误......
答案 0 :(得分:0)
正式地,函数test_init
在代码中使用,语言需要定义。
但是,智能编译器可能会发现if
保护的分支从未执行过,并取消了对test_init
的调用。如果编译器消除了对函数的所有调用,那么典型的实现可能无法诊断问题,因为该函数实际上 未使用。具有外部链接的实体的“缺失定义”问题通常在链接阶段被诊断出来。当链接器无法匹配函数定义的函数调用时,将报告错误。如果没有电话,则无需匹配任何内容。
但是,再次,这不是你可以依赖的东西。在语言层面,没有“静态如果”这样的功能。正式C语言不允许您保留未定义的此类函数,即使它们受编译时已知条件的if
保护。
答案 1 :(得分:0)
您无法依赖简单的C if
来删除函数调用。碰巧编译器优化了测试
if(test_is_supported())
到
if(false)
通过内联,然后进一步优化后续test_init()
作为死代码。
但,这些优化无法保证。例如,如果您在没有优化的情况下进行编译,那么优化的可能性很小,并且将生成函数调用。在这种情况下,即使它永远不会执行,链接器也需要定义函数,否则它将失败。
更安全的方法是使用#if
完全删除代码:
#if CONFIG_TEST
if(test_is_supported())
test_init();
#endif
如果if
未定义(即未定义CONFIG_TEST
),这将保证test_init()
及后续代码不会被编译。