我的文件结构是这样的:
- FileA
- FileB
- FileC
FileA包含FileB和FileC
FileB有:
#define image(i, j, w) (image[ ((i)*(w)) + (j) ])
and FileC has:
#define image(i, j, h) (image[ ((j)*(h)) + (i) ])
编译得到:
warning: "image" redefined
note: this is the location of the previous definition ...
这个警告是否意味着它改变了编译时最初找到它的另一个文件的定义?
在维护这两个定义并在各自的文件上应用它们的不同定义时,是否有任何方法可以避免此警告?
谢谢你提前:)
这个警告是否意味着它改变了编译时最初发现的另一个文件的定义?
程序格式错误。语言没有说明在这种情况下会发生什么。如果编译器接受了一个格式错误的程序,那么你必须阅读编译器的文档来了解它们在这种情况下是怎么做的。
注意,该程序甚至可能无法与其他编译器编译。
是否有任何方法可以避免此警告,同时维护这两个定义,并在各自的文件上应用它们的不同定义?
从技术上讲,你可以像这样使用hack而不触及任何头:
#include "FileB"
#undef image
#include "FileC"
但是一个好的解决方案-如果你可以修改头-是不使用宏。编辑标题以删除它们。使用函数代替,并在不同的命名空间中声明它们,这样它们的名称就不会冲突。
一些经验法则:
- 不要使用不必要的宏。函数和变量优于宏。
- 如果您绝对需要使用宏,请遵循仅使用大写字母的通用约定。确保宏名称不与非宏混淆是很重要的,因为宏不尊重名称空间和作用域。
- 如果你需要在单个头文件中使用宏,那么在不再需要它时立即取消定义,而不是将它泄漏到其他头文件中。
- 不要使用没有名称空间的名称。这将导致名称冲突。宏不尊重c++的命名空间,但是你可以用前缀代替它们的名字。例如,您可以使用
FILE_B_IMAGE
和FILE_C_IMAGE
(或基于具体上下文的更具描述性的内容)。
它们在功能上并不等同,一个可以看作是逐行迭代,另一个可以看作是逐列迭代
这似乎是重命名函数(或宏,如果由于某种原因不能替换它们)的好理由。一个叫row_wise
,另一个叫column_wise
或者沿着这条线。使用描述性的名字!
这个警告是否意味着它改变了编译时最初发现的另一个文件的定义?
对于GCC(有标记的),这意味着从重新定义开始就使用第二个处理过的定义,不仅包括在同一个文件中,还包括在翻译单元中宏标识符后面跟着(
的任何地方。之前的出现将使用之前的定义
C语言规范和c++语言规范都没有提供更一般的答案:除了使用相同的标记序列之外的重定义违反了语言约束,因此包含这种不匹配重定义的程序的翻译行为和执行行为都是未定义的。
是否有办法在保持这两个时避免此警告定义,他们将不同的定义应用于他们的各自的文件?
如果这些定义只能在它们各自的文件中使用,那么最简单的解决方案是在每个文件的末尾使用#undef image
。这在C和c++中都可以工作。
如果这两个文件都打算公开供其他文件使用,那么就会出现名称冲突,必须以某种方式解决。例如,您可以为定义和每个定义的所有用法添加一个区分前缀。仅在c++中,您还可以通过将宏更改为[内联]函数并将它们放在不同的命名空间中来解决名称冲突。这可能会使每个用户更容易适应新名称,而不是给名称加上前缀。