【问题标题】:How to initialize a std::array<char, N> with a string literal omitting the trailing '\0'如何使用省略尾随 '\0' 的字符串文字初始化 std::array<char, N>
【发布时间】:2015-11-02 18:16:27
【问题描述】:

我有一个文件结构,其中固定长度的字符串没有尾随零。 如何将字段初始化为 std::array 而不尾随零:

#pragma pack(push, 1)
struct Data {
    // Compiles, but it has an undesired '\0':
    std::array<char, 6> undesired_number{"12345"};
    // Does not compile:
    std::array<char, 5> number{"12345"}; // stripping '\0'
};
#pragma pack(pop)

【问题讨论】:

  • 什么是编译器错误?不兼容的类型?恐怕基于字符串文字根本不可能。
  • 为什么一定要用字符串字面量来初始化呢?
  • @Barmar 只是为了方便
  • 由于字符串文字总是附加'\0' 或等价物,我的赌注是一些中间的constexpr/template 魔法,它会采用文字并去掉零并返回一个截断的值。但是它可能有问题,因为您不能修改字符串文字。也许常量表达式的例外允许它。
  • 你可以制作一个用户定义的文字

标签: c++ arrays c++11


【解决方案1】:

制作辅助函数

template <std::size_t N, std::size_t ... Is>
constexpr std::array<char, N - 1>
to_array(const char (&a)[N], std::index_sequence<Is...>)
{
    return {{a[Is]...}};
}

template <std::size_t N>
constexpr std::array<char, N - 1> to_array(const char (&a)[N])
{
    return to_array(a, std::make_index_sequence<N - 1>());
}

然后

struct Data {
    std::array<char, 5> number{to_array("12345")}; // stripping '\0'
};

Demo

【讨论】:

  • 我想知道这是否会编译成文字的一个副本,或者两个,一个带有终止符,一个没有。
  • @luk32,取决于编译器和优化设置。例如,带有 O3 的 g++ 根本没有文字。
  • 在获得make_index_sequence 并更改为std::array&lt;char, 5&gt; number = to_array("12345"); 后与C++11 很好地配合
  • @VioletGiraffe: std::array 主要是struct { T data[N]; };,所以在聚合初始化时,第一个括号是类array,第二个是它的data 成员。 (一对可以省略,但编译器可能会警告“缺少”大括号)。
  • @303:使用默认可初始化类型,例如char,您确实可以使用 for-range(即使从 C++14 开始(constexpr 函数中允许使用 for-range,并且std::array 的方法标记为 constexpr))。您不能使用 for-range 初始化,只能分配/复制,这对 char 来说很好。
【解决方案2】:

字符串文字以 NUL 结尾的,在 C++ 中(与 C 不同),您不能通过提供 Length - 1 大小来取消它;因此它不能直接完成,同时考虑到array内部是T[N]

【讨论】:

  • 标准不要求 array 在内部是 T[N]。对于N &gt; 0 的情况,有些人认为应该这样做
猜你喜欢
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 2017-05-06
  • 2020-07-30
  • 2015-03-22
  • 1970-01-01
  • 2018-04-29
  • 2022-11-17
相关资源
最近更新 更多