9

更新

原来这只是“c++ is not c blues”的另一种情况


我想要的是

const char hex[16] = "0123456789ABCDEF";

唯一有效的

char hex[16] = "0123456789ABCDE"; hex[15] = "F";

是否有任何编译器选项或我可以做些什么来使字符串在 gcc 编译器中不为空终止。这样我就可以制作一个(n)常量数组

4

6 回答 6

11

不需要编译器选项,它已经是非 NUL 终止的。该标准规定,只有在可以适合的情况下才应添加 NUL,否则将是溢出。可能只是数组中的下一个字节是\0

§ 6.7.8p14

字符类型的数组可以由字符串字面量初始化,可选地用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。

于 2010-12-03T17:32:52.163 回答
9

不,以 NUL 结尾的字符串是该语言固有的。你可以有一个字符数组,并一个一个地设置每个字符:

char hex [] = {'0', '1', '2', ... 'F'};
于 2010-12-03T17:31:51.830 回答
5

你是在自问自答。如果你明确地给数组一个长度,如下所示:

const char hex[16] = "0123456789ABCDEF";

那么它当然不会被空终止,因为没有为空终止保留存储。(hex[16]在对象的范围之外,因此读取或写入它是未定义的行为。如果它恰好读为 0,那是你的 UB ......)

仅当您将长度保留为隐式时,如下所示:

const char hex[] = "0123456789ABCDEF";

或者,如果您将字符串文字用作对象而不是初始化程序,则它将具有空终止。

顺便说一句,如果您不打算使用它,为什么还要关心是否存在空终止。您是否要从二进制文件中删除字节?:-)

于 2010-12-03T17:43:25.557 回答
1

我相信这个问题有点不清楚:在 C 中,引用的初始化:

static const char hex[16] = "0123456789ABCDEF";

是合法的。在 C++ 中,它不是。因此,当您从 C 迁移到 C++ 时,它是失败的代码之一(幸运的是在编译时)。

有一种方法可以在不终止 \0 字节的情况下强制字符串文字。就像是:

static const char hex[16] = "0123456789ABCDEF\!0";

最后\!0告诉编译器不要以零结尾的字符串!\!甚至\!0字符串中的其他任何地方都不会被修改,所以只需输出一个文字!!0.

于 2014-11-16T10:34:16.863 回答
1

在 C++17 中实际上有一个解决这个问题的部分方法:constexpr函数可能返回类型为 的对象std::array。因此,我们不是初始化一个 const C 数组,而是初始化一个 constexpr C++ std::array。此模板函数剥离终止符:

template<typename CHAR, unsigned long N>
constexpr inline std::array<CHAR, N-1> strip_terminator(const CHAR (&in)[N])
{
    std::array<CHAR, N-1> out {};
    for(unsigned long i = 0; i < N-1; i++) {
        out[i] = in[i];
    }
    return out;
}

它可以按如下方式使用:

constexpr std::array<char, 16> hex = strip_terminator("0123456789ABCDEF");

一切都在编译时完成,即使优化关闭:数组hex成为所需大小和所需内容的常数,没有不需要的零终止字节。

于 2021-05-13T15:56:50.853 回答
0

字符串在 C 中以 null 结尾。如果要填充非 null 终止的 char 数组,可以使用数组初始值设定项。

于 2010-12-03T17:32:48.413 回答