简体   繁体   English

在头文件中使用`const char thing [] =“foo”;`

[英]use `const char thing[] = “foo”;` in a header file?

I want to create a constant global char array such that 我想创建一个常量全局char数组

  • It can be used in multiple translation units. 它可以用于多个翻译单元。
  • The length of the array is deduced from the string literal used to initialize it. 数组的长度是从用于初始化它的字符串文字中推导出来的。
  • That string literal exist exactly once in my source (and if possible the object files). 该字符串文字在我的源代码中只存在一次(如果可能的话,还有目标文件)。
  • Where all the translation unit have compile time access to the length. 所有翻译单元都有编译时间访问的长度。
  • Has no ODR violations when the multiple translation units are linked together. 多个翻译单元链接在一起时没有ODR违规。

In theory this should be possible by using const char[] and putting the deceleration/definition in the header file in a way that forces the data/symbol into a COMDAT section, but I don't know if the standard (or even any compilers) support that. 理论上应该可以通过使用const char[]并将减速/定义放在头文件中,以强制数据/符号进入COMDAT部分,但我不知道标准(甚至是任何编译器) )支持。

ps Assume whatever idiom is used will be used for hundreds to thousands of constants across many files. ps假设使用的任何习语将用于跨越许多文件的数百到数千个常量。


Edit: the "cleanest" solution I know of that give all the points is: 编辑:我所知道的“最干净”的解决方案是:

template<bool> struct data_ {
  static const char kFoo[];
};

template<> const char data_<true>::kFoo[] = "bar\0other\0stuff\0";
typedef data_<true> data;


#include <stdio.h>

template<typename T, int N>
void Print(T(&var)[N]) { printf("%d %s\n", N, var); }

int main() { Print(data::kFoo); return 0; }

Which is still rather ugly. 这还是比较丑陋的。


OTOH If I just throw out 3b (guaranteed same storage module inlineing) then this work: OTOH如果我只丢掉3b(保证相同的存储模块内联),那么这项工作:

const char kFoo[] = "bar\0other\0stuff\0";

because it's has internal linkage by default. 因为它默认有内部链接。 A good linker could merge these, but at that point you can't say anything about the the relationship between the equality of the addresses/identifiers (ie don't cast it to a pointer and use that as an identity). 一个好的链接器可以合并这些,但是在这一点上你不能说出地址/标识符相等之间的关系(即不要将它转换为指针并将其用作标识)。 But that's a caveat that's likely to be benign almost all of the time. 但这是一个几乎所有时间都可能是良性的警告。

Header: 标题:

#define LITERAL "Hello, world"
extern char const literal[sizeof LITERAL];

One source file: 一个源文件:

char const literal[] = LITERAL;

There's still no guarantee that any particular compiler/linker only make one copy of the string literal (but it does guarantee the requirement that &literal[0] is the same in all units). 仍然无法保证任何特定的编译器/链接器只能生成字符串文字的一个副本(但它确保要求&literal[0]在所有单元中都相同)。

Since C++17 you can write in the header: 从C ++ 17开始,您可以在标题中写入:

inline char const thing[] = "foo";

which meets all the criteria. 符合所有标准。

Note: inline variables have external linkage unless explicitly declared as static . 注意: inline变量具有外部链接,除非显式声明为static The rule about const variables defaulting to internal linkage only applies to non-inline variables. 关于const变量默认为内部链接的规则仅适用于非内联变量。

你不想要

const char * const LITERAL="foo";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM