原来这只是“c ++不是c布鲁斯”的另一个案例
我想要什么
const char hex[16] = "0123456789ABCDEF";
唯一有效的方法
char hex[16] = "0123456789ABCDE"; hex[15] = "F";
是否有任何编译器选项或我可以做的事情使gcc编译器中的字符串不为空终止。这样我就可以制作一个(n)常数数组
答案 0 :(得分:11)
不需要编译器选项,已经非NUL终止。标准说只有在NUL适合的情况下才应添加NUL,否则它将是溢出。可能只是内存中的下一个字节超过了数组\0
§6.7.8p14
一个字符数组 type可以由一个字符初始化 字符串文字,可选 用括号括起来。字符串的连续字符 文字( 包括 如果有空间 或者数组是空的,则终止空字符 未知大小)初始化 数组的元素。
答案 1 :(得分:7)
不。以NULL结尾的字符串是该语言的固有字符串。您可以拥有一个字符数组,并逐个设置每个字符:
char hex [] = {'0', '1', '2', ... 'F'};
答案 2 :(得分:5)
你回答了自己的问题。如果明确给出数组长度,如:
const char hex[16] = "0123456789ABCDEF";
然后它当然不会以空值终止,因为没有为空终止保留的存储空间。 (hex[16]
超出了对象的范围,因此读取或写入它是未定义的行为。如果它恰好读为0,那就是你的UB ...)
只有当你隐藏长度时,才会这样:
const char hex[] = "0123456789ABCDEF";
或者如果您将字符串文字用作对象而不是初始化程序,则它将具有空终止。
顺便说一下,如果您不打算使用它,为什么还要关心是否存在空终止。您是否想要从二进制文件中删除字节? : - )
答案 3 :(得分: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
变成了一个具有所需大小和所需内容的常量,没有不需要的零终止字节。
答案 4 :(得分:0)
字符串在C中以空值终止。如果要填充非空终止的char数组,可以使用数组初始值设定项。
答案 5 :(得分:0)
我认为这个问题有点不清楚:在C中,qoted初始化:
static const char hex[16] = "0123456789ABCDEF";
是合法的。在C ++中,它不是。因此,当你从C转向C ++时,它是失败的一部分(幸运的是在编译时)。
有一种强制字符串文字而没有终止\ 0字节的方法会很好。类似的东西:
static const char hex[16] = "0123456789ABCDEF\!0";
最后\!0
告诉编译器不要对字符串进行零终止! \!
甚至\!0
字符串中的任何其他位置都会保持不变,因此只需输出文字!
或!0
。