C 如何存根声明为“0”的变量/函数;外部无效;

C 如何存根声明为“0”的变量/函数;外部无效;,c,unit-testing,gcc,C,Unit Testing,Gcc,我需要对c文件/模块进行单元测试,该文件包含: /* Import the _x symbol from assem.S */ extern void _x; 该变量稍后在该文件中用作: #define WHAT_EVER (int)&_x 汇编程序文件中的减速为: .global _x .type _x, @function _x: 我了解到GCC同意这个声明。 然而,我知道我不能简单地声明: void _x; 作为我的存根,因为这使得x是一个不完整的类型。实际上,链接器会抱怨

我需要对c文件/模块进行单元测试,该文件包含:

/* Import the _x symbol from assem.S */
extern void _x;
该变量稍后在该文件中用作:

#define WHAT_EVER (int)&_x
汇编程序文件中的减速为:

.global _x
.type _x, @function
_x:
我了解到GCC同意这个声明。 然而,我知道我不能简单地声明:

void _x;
作为我的存根,因为这使得x是一个不完整的类型。实际上,链接器会抱怨错误:“\u x”的存储大小未知,链接器是正确的

但如果我宣布:

int _x;
编译器给了我错误:'\u x'的类型冲突,这也是正确的

软件的目标与我进行单元测试的主机不同,因此我不能包含assem.S文件(它不会在我的主机上编译和/或运行)

有人知道存根这个变量的方法吗?


通用条款5.3.1;std=gnu99;c code

如果您可以选择修改引用了
\u x
的文件,则应将对此符号的访问权提取到其自己的文件中。首先,我将解释你如何做到这一点,其次,你为什么要这样做

如何提取?在测试中的现有文件中,可以通过调用访问函数替换对符号的所有访问。也就是说,不使用宏
WHAT\u EVER
的值进行读取,而是调用
get\u WHAT\u EVER()
。如果使用符号修改地址,则调用
set\u what\u ever(value)
。这些getter和setter函数在一个单独的文件中实现(例如,让我们称之为
interface\u to_assembly.c
)。声明放在头文件
interface\u to_assembly.h
中。现在,对于您的目标系统,编译并链接修改后的文件和
接口\u到\u assembly.c
。对于测试可执行文件,您可以为
interface\u to\u assembly.c
创建一个替代实现,可能是
interface\u to\u assembly\u double.c
。这些替代实现可以是dummys、stub、spy、mock或测试所需的任何东西


为什么这种分离是可取的?首先,它消除了要从程序集级别测试的代码与硬件之间的紧密耦合。其次,它用更好的可控函数接口取代了对全局变量的访问。但是,请注意,文件
interface_to_assembly.c
中的一小段软件的可测试性仍然不会比以前更好(也就是说,它将成为目标系统上集成测试的候选对象)。但是,对于剩下的代码(可能是大多数代码),您的可测试性有了很大的提高:提取变量访问并用函数替换它,这样就可以在不使用任何汇编级代码的情况下编译代码。它允许控制每个单值访问。例如,可以创建一个测试设置,以使对getter的连续调用提供不同的值(如果您想模拟硬件设备的并发活动,这一点很重要)。

如果您可以选择修改引用了
\u x
的文件,您应该将对此符号的访问权提取到其自己的文件中。首先,我将解释你如何做到这一点,其次,你为什么要这样做

如何提取?在测试中的现有文件中,可以通过调用访问函数替换对符号的所有访问。也就是说,不使用宏
WHAT\u EVER
的值进行读取,而是调用
get\u WHAT\u EVER()
。如果使用符号修改地址,则调用
set\u what\u ever(value)
。这些getter和setter函数在一个单独的文件中实现(例如,让我们称之为
interface\u to_assembly.c
)。声明放在头文件
interface\u to_assembly.h
中。现在,对于您的目标系统,编译并链接修改后的文件和
接口\u到\u assembly.c
。对于测试可执行文件,您可以为
interface\u to\u assembly.c
创建一个替代实现,可能是
interface\u to\u assembly\u double.c
。这些替代实现可以是dummys、stub、spy、mock或测试所需的任何东西


为什么这种分离是可取的?首先,它消除了要从程序集级别测试的代码与硬件之间的紧密耦合。其次,它用更好的可控函数接口取代了对全局变量的访问。但是,请注意,文件
interface_to_assembly.c
中的一小段软件的可测试性仍然不会比以前更好(也就是说,它将成为目标系统上集成测试的候选对象)。但是,对于剩下的代码(可能是大多数代码),您的可测试性有了很大的提高:提取变量访问并用函数替换它,这样就可以在不使用任何汇编级代码的情况下编译代码。它允许控制每个单值访问。例如,可以创建一个测试设置,这样对getter的连续调用就可以传递不同的值(如果要模拟硬件设备的并发活动,这一点很重要)。

如何在汇编文件中定义
x
?如果它是一个四字节整数(使用例如
dd
),那么您可以将它声明为
extern int32_t_x
@Joachim在汇编文件中声明的值被添加到问题中。@Joachim
extern int32_t_x
int_x
冲突类型的结果不一样。更多问题:a)如何使用“WHAT_曾经”,或者,也许更重要的是,为什么要“存根”价值?只是为了使其可编译,还是需要控制测试中的值?b) 您是否可以选择修改要测试的文件?@Dirk WHAT\u EVER用作
struct.array[number]=WHAT\u EVER它看起来像处理器的一些初始化。在