4

我想创建一个常量全局字符数组,这样

  • 它可以在多个翻译单元中使用。
  • 数组的长度是从用于初始化它的字符串文字推导出来的。
  • 该字符串文字在我的源文件中仅存在一次(如果可能,在目标文件中)。
  • 其中所有的翻译单元都有编译时访问的长度。
  • 当多个翻译单元链接在一起时,没有 ODR 违规。

从理论上讲,这应该可以通过使用const char[]减速/定义并将其放入头文件中,以强制数据/符号进入 COMDAT 部分,但我不知道标准(甚至任何编译器)是否支持。

ps 假设使用的任何习语都将用于许多文件中的数百到数千个常量。


编辑:我所知道的给出所有要点的“最干净”的解决方案是:

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; }

这仍然是相当丑陋的。


OTOH 如果我只是扔掉 3b (保证相同的存储模块内联),那么这项工作:

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

因为默认情况下它具有内部链接。一个好的链接器可以合并这些,但此时你不能说地址/标识符的相等性之间的关系(即不要将其转换为指针并将其用作标识)。但这是一个警告,可能几乎一直都是良性的。

4

3 回答 3

2

标题:

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

一个源文件:

char const literal[] = LITERAL;

仍然不能保证任何特定的编译器/链接器只制作字符串文字的一份副本(但它确实保证&literal[0]所有单元中的要求都是相同的)。

于 2014-09-22T21:59:03.613 回答
1

从 C++17 开始,您可以在标题中写入:

inline char const thing[] = "foo";

符合所有标准。

注意: inline变量具有外部链接,除非明确声明为static. 关于const变量默认为内部链接的规则仅适用于非内联变量。

于 2018-05-02T01:33:31.227 回答
-3

你不想

const char * const LITERAL="foo";
于 2014-09-22T18:12:24.803 回答