更新
原来这只是“c++ is not c blues”的另一种情况
我想要的是
const char hex[16] = "0123456789ABCDEF";
唯一有效的
char hex[16] = "0123456789ABCDE"; hex[15] = "F";
是否有任何编译器选项或我可以做些什么来使字符串在 gcc 编译器中不为空终止。这样我就可以制作一个(n)常量数组
原来这只是“c++ is not c blues”的另一种情况
我想要的是
const char hex[16] = "0123456789ABCDEF";
唯一有效的
char hex[16] = "0123456789ABCDE"; hex[15] = "F";
是否有任何编译器选项或我可以做些什么来使字符串在 gcc 编译器中不为空终止。这样我就可以制作一个(n)常量数组
不需要编译器选项,它已经是非 NUL 终止的。该标准规定,只有在可以适合的情况下才应添加 NUL,否则将是溢出。可能只是数组中的下一个字节是\0
§ 6.7.8p14
字符类型的数组可以由字符串字面量初始化,可选地用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。
不,以 NUL 结尾的字符串是该语言固有的。你可以有一个字符数组,并一个一个地设置每个字符:
char hex [] = {'0', '1', '2', ... 'F'};
你是在自问自答。如果你明确地给数组一个长度,如下所示:
const char hex[16] = "0123456789ABCDEF";
那么它当然不会被空终止,因为没有为空终止保留存储。(hex[16]
在对象的范围之外,因此读取或写入它是未定义的行为。如果它恰好读为 0,那是你的 UB ......)
仅当您将长度保留为隐式时,如下所示:
const char hex[] = "0123456789ABCDEF";
或者,如果您将字符串文字用作对象而不是初始化程序,则它将具有空终止。
顺便说一句,如果您不打算使用它,为什么还要关心是否存在空终止。您是否要从二进制文件中删除字节?:-)
我相信这个问题有点不清楚:在 C 中,引用的初始化:
static const char hex[16] = "0123456789ABCDEF";
是合法的。在 C++ 中,它不是。因此,当您从 C 迁移到 C++ 时,它是失败的代码之一(幸运的是在编译时)。
有一种方法可以在不终止 \0 字节的情况下强制字符串文字。就像是:
static const char hex[16] = "0123456789ABCDEF\!0";
最后\!0
告诉编译器不要以零结尾的字符串!\!
甚至\!0
字符串中的其他任何地方都不会被修改,所以只需输出一个文字!
或!0
.
在 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
成为所需大小和所需内容的常数,没有不需要的零终止字节。
字符串在 C 中以 null 结尾。如果要填充非 null 终止的 char 数组,可以使用数组初始值设定项。