C 如何防止符号重新定义

C 如何防止符号重新定义,c,eclipse,typedef,redefinition,codewarrior,C,Eclipse,Typedef,Redefinition,Codewarrior,我的项目包含一个堆栈,它有许多用户定义的类型(typedef)。问题是这些类型定义中的许多与我们内部的类型定义冲突。也就是说,正在使用相同的符号名称。有没有办法防止这种情况发生 问题的根源在于,要在应用程序中使用堆栈或包装器代码(视情况而定),必须包含特定的头文件。此堆栈头文件依次包括堆栈提供程序的类型定义文件。这就是问题所在。他们应该通过非公共包含路径包含类型定义文件,但他们没有。现在,对于非常常见的名称,存在各种用户定义的类型冲突,例如BYTE、WORD、DWORD,等等。由于您可能无法轻松

我的项目包含一个堆栈,它有许多用户定义的类型(
typedef
)。问题是这些类型定义中的许多与我们内部的类型定义冲突。也就是说,正在使用相同的符号名称。有没有办法防止这种情况发生


问题的根源在于,要在应用程序中使用堆栈或包装器代码(视情况而定),必须包含特定的头文件。此堆栈头文件依次包括堆栈提供程序的类型定义文件。这就是问题所在。他们应该通过非公共包含路径包含类型定义文件,但他们没有。现在,对于非常常见的名称,存在各种用户定义的类型冲突,例如
BYTE
WORD
DWORD
,等等。

由于您可能无法轻松更改正在使用的程序堆栈,因此您必须从自己的代码开始

首先要做的是(显然)尽可能限制全局名称空间中的名称数量。例如,不要使用全局变量,只使用静态变量

下一步是为代码模块采用命名约定。假设项目中有一个“输入模块”。例如,您可以在输入模块“inp”中为所有函数添加前缀

等等。当这些项在代码中的其他地方使用时,它们不仅具有唯一标识符,而且对于读者来说,它们属于哪个模块以及它们的用途也是显而易见的。因此,在修复名称空间冲突的同时,您可以获得可读性


类似于上面的内容可能是实现正式编码标准的第一步,作为一名专业程序员,您迟早要做这件事。

我建议您定义一个包装头,根据自己的类型重新定义堆栈导出的所有函数和结构。然后,此标头将包含在系统文件中,但不会包含在堆栈文件中(在堆栈文件中,它会发生冲突)。然后可以编译和链接,但接口有一个弱点。如果您在重新定义中正确选择了类型,它应该可以正常工作,只会在堆栈供应商的每次更新中留下一个维护问题

我认为目前我已经找到了一个合理的解决方案,但正如Lundin所说,长期解决方案需要一个正式的编码标准


基本上,我所做的是将所需堆栈头文件的包含移到内部类型定义文件的包含之前。然后,在这两个包含之间,我添加了一个编译器宏来设置一个定义的常量,该常量取决于堆栈的头文件single include保护定义是否已定义。然后,我在内部类型定义文件中将该条件定义常量用作条件编译选项,以防止重新定义冲突的数据类型。这有点草率,但只能循序渐进地取得进展。

你能在堆栈周围加上一个包装吗?@WilliamMorris这就是我要做的,这就是为什么需要解决这些差异。问题的根源是:为什么你首先会遇到命名冲突?堆栈是否未使用任何适当的命名约定,或者它是应用程序,或者两者都使用?是否与标准C库(又名bug)存在冲突?我认为这并不能解决问题。据我所知,系统的两侧使用相同的名称定义类型。这意味着由于重新定义错误,输入堆栈不能包含系统头,系统也不能包含堆栈头。即使它们定义了相同的类型(包括相反的头),也不会编译。@williamorris堆栈不会包含应用程序的其余部分,这是没有意义的。这可能是一些通信协议栈、TCP/IP、CANopen、以太网等等。它将位于程序的较低硬件层,而调用者是实际的应用程序。因此,调用者有责任避免命名冲突。无论如何,这在问题中给出的有限信息中并不明显。不,我知道堆栈不会包括应用程序标题。但是想象一下,您想要编写一个包装器来连接这两个。您希望包括堆栈头,将其函数转换为您的类型,然后导出转换后的函数。但是你不能这样做,因为当你试图在包装器和堆栈的头中包含你自己的头时,它们会发生冲突。@Lundin感谢你提出的深思熟虑的建议。您实现的命名约定与我在代码模块上实现的命名约定非常相似。我最近被一家非常小的公司聘请为他们的第一位工程师,100%致力于固件开发。目前的情况是,他们现有的大部分代码库。。。需要注意。@JimFell我自己也很熟悉这种情况:)在一家小公司里单独制定一个正式的编码标准,是一项艰巨的工作,但最终还是值得的。我强烈建议使用作为基础,从中选择您喜欢的,然后作为下一步,决定代码格式和命名规则。这使您的项目从属于堆栈,这听起来很奇怪。如果堆栈以不兼容的方式更改其定义,那么您可能必须更改项目的类型定义文件(我想这是一个非常重要的文件),而不仅仅是更改我建议的包装文件。最有可能的情况是,这样的更改不会发生,所以问题不会出现,但我更喜欢依赖关系的另一种方式:-)请注意,您的解决方案还意味着您的一些源文件及其包含的任何头文件将使用来自项目的类型定义和其他使用堆栈的类型定义进行编译,(以及它们包含的任何头)将使用源自堆栈的类型定义进行编译。这可能会导致微妙的错误
void inp_init (void); 
void inp_get  (int input);

#define INP_SOMECONSTANT 4

typedef enum
{
  INP_THIS,
  INP_THAT,
} inp_something_t;