GCC可以忽略函数的静态声明吗?

时间:2016-05-27 12:53:25

标签: c unit-testing gcc

在我的应用程序中,我有一个用于伪单元测试的构建配置(这是一种手动调试专用功能)。

在这些单元测试中,我想在其翻译单元中访问声明为static的函数。

是否有GCC选项允许我从任何地方拨打static个功能?

我想避免:

#if UNIT_TEST_MODE
void myfunction(void)
#else
static void myfunction(void)
#end
{
    // body
}

到处!

感谢您的帮助:)。

4 个答案:

答案 0 :(得分:4)

不需要冗长。为每个静态函数使用前缀define:

#if UNIT_TEST_MODE
#define UNIT_TEST_STATIC
#else
#define UNIT_TEST_STATIC static
#end

UNIT_TEST_STATIC void myfunction(void)
{
    // body
}

另一种选择是将所有静态函数从该.c文件移动到单独的标头。该标头仅包含在该.c文件中,但如果需要,它可以包含在单元测试.c文件中。除非手动包含标题,否则这些功能在其他文件中将保持不可见  (它们必须被定义为静态内联。)

答案 1 :(得分:2)

应用于函数或文件范围变量时,static关键字表示声明的函数或对象具有内部链接。这意味着只能从同一翻译单元中直接引用这样的函数或对象。海湾合作委员会没有选择改变C语言的核心条款,也不应该改变。

那么,您的替代方案要么

  • 为有问题的函数提供外部联系而不是内部联系,可能是有条件的,或者

  • 通过间接机制使测试代码可用,例如函数指针初始化并由翻译单元内的某个工具(另一个函数,全局变量)提供给测试代码。

第一种选择更简单,但使用它意味着被测代码并不完全等同于为普通用途构建的代码。此外,如果任何以前静态函数的名称与其他全局对象的名称冲突,则此选项不可行。此选项已在其他答案中得到充分论证,因此我不会在此处进一步详细说明。

第二种选择的优点和缺点或多或少是第一种选择的镜像。它更复杂,但是可以使用它们在生成构建中使用的相同形式测试函数,并且可以避免此路由发生名称冲突。这种方法有许多可能的变化;这是一个:

test_header.h

#ifndef TEST_HEADER_H
#define TEST_HEADER_H

struct test_pointers {
    int (*function_to_test)(const char *);
};

void initialize_test_pointers(struct test_pointers *pointers);

#endif

module_under_test.c

static int function_to_test(const char *);

#ifdef ENABLE_TESTING

#include "test_header.h"

extern void initialize_test_pointers(struct test_pointers *pointers) {
    pointers->function_to_test = function_to_test;
}

#endif

static int function_to_test(const char *s) {
    // ... whatever
}

the_test.c

#include "test_header.h"

int test_it(void) {
    struct test_pointers pointers;
    char test_input[] = "test THIS!";
    const int expected_result = 42;
    int result;

    initialize_test_pointers(&pointers);
    result = pointers.function_to_test(test_input);

    return result == expected_result;
}

答案 2 :(得分:0)

不,它不能。此关键字指定函数的可见性,仅作为翻译单元,由launguage标准定义。编译器忽略它会使它不符合。

UPD。要解决您的问题,您确实可以执行预处理程序指令技巧,如您对问题的评论中所述。

答案 3 :(得分:0)

这不能解答您关于GCC的问题,但作为单元测试问题的解决方案,您可以在同一模块中有条件地编译包装函数,

static void myfunction(void)
{
    // body
}

#if UNIT_TEST_MODE
void myfunction_test(void)
{
    myfunction();
}
#endif

或者,您可以从单元测试包装文件中#include模块

// unit_test.c
#include "myfunction.c"
void unit_test()
{
    myfunction();
}