char* 数组出现“多个定义”错误,但 unsigned char 数组不出现
Posted
技术标签:
【中文标题】char* 数组出现“多个定义”错误,但 unsigned char 数组不出现【英文标题】:"multiple definitions" error appears for char* arrays but not for unsigned char arrays 【发布时间】:2015-01-13 09:46:24 【问题描述】:我正在重构一个 c++ 代码,但有些东西我无法理解。该代码在头文件中声明一组数组,然后在需要时将该头文件包含在源文件中。所有数组都是“const unsigned char[]”,除了一个是“const char *[]”数组。后者被#ifdef SOMETHING 包围。如果 SOMETHING 未定义,则代码构建成功,否则我仅得到此“char * []”的多个定义的链接器错误。
作为修复,我可以通过将“static”添加到“const char* XX[3] = "X", "Y", "Z"" 来消除这些链接器错误。这将保留特定于翻译单元的定义。
但是,我无法理解为什么“多重定义”错误只发生在“const char* []”数组中而不发生在其他“const unsigned char[]”数组中,尽管它们前面没有“静态”关键字?有人可以向我解释一下吗?
【问题讨论】:
不要define头文件中的数组,只declare它们。例如,const char* XX[3] = "X", "Y", "Z";
是一个定义。
是的,Joachim,我知道按照你说的做会更好,但我的问题是不同的,它是关于链接器错误,为什么只为 char*[] 而不是 unsigned char[] 得到的跨度>
关键区别在于const
,而不是*
或unsigned
。 const unsigned char[]
是一个 const 数组,const char*[]
是一个非常量数组(由 const 指针组成)。
【参考方案1】:
命名空间范围内的常量变量隐含地具有内部链接(如果您愿意,它们隐含为static
)。下面声明并定义了两个不同的对象。
// A.cpp // B.cpp
const T foo = 1; const T foo = 2;
如果你想要外部链接,你必须说extern const T foo;
。
相比之下,命名空间范围内的非常量变量具有外部链接(如果您愿意,它们被隐式声明为extern
)并且都表示同一个对象,因此您违反了单一定义规则:
// A.cpp // B.cpp
U bar = 1; U bar = 2; // ODR violation
这里,如果你想要内部链接,你必须说static U bar;
。
这是你的情况。你有T = char []
和U = const char * []
。 (这里const T
由 8.3.4/1 生成 const char []
类型。)
如果变量具有外部链接,则解决方案是不在标题中定义变量,因为标题包含在多个翻译单元中。相反,只需声明标题中的变量并将其定义在一个翻译单元中:
library.h:
extern U bar; // in your case, extern const char * XX[];
library_impl.cpp:
#include "library.h"
U bar = 3;
【讨论】:
感谢您的回答。但是,为什么您将“const char* []”视为命名空间中的“非常量”。我仍然无法理解这一点。请您澄清一下。 @Aymen:因为它是非常量的。是什么让你认为它是恒定的? (提示:请确保您了解 C++ 类型声明语法。) @Aymen:“在命名空间范围内”是 C++ 的“全局变量”的说法。只是“全局”不是很精确,因为 C++ 有命名空间,但本质上就是这样。 @Aymen:你不能把随机的东西断章取意。您的类型是U = V *
,与const U = V * const
不同。 V = const char
的事实无关紧要。你有一个指针,并且指针是可变的。确实,指针指向不可变的东西,但这与指针本身无关。您将const char *
与char * const
混淆了。
谢谢。你太快了:)以上是关于char* 数组出现“多个定义”错误,但 unsigned char 数组不出现的主要内容,如果未能解决你的问题,请参考以下文章
如何将C++中string类型的字符串赋给unsigned char数组
我想定义一个字符串指针数组,使用下面语句: static char *ch[10]; 但提示错误,求解