未使用功能的功能原型

时间:2017-03-24 01:05:51

标签: c compilation

我正在处理一段将用于多个项目的代码,我刚刚意识到如果函数的调用受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。

编辑:纠正了函数名称的一些错误......

2 个答案:

答案 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()及后续代码不会被编译。