C++ gcc的非空终止字符串编译器选项 更新

C++ gcc的非空终止字符串编译器选项 更新,c++,c,string,gcc,null-terminated,C++,C,String,Gcc,Null Terminated,事实证明,这只是“c++不是c布鲁斯”的另一个例子 我想要什么 const char hex[16] = "0123456789ABCDEF"; 唯一有效的方法 char hex[16] = "0123456789ABCDE"; hex[15] = "F"; 是否有任何编译器选项或我可以做的事情,使字符串在gcc编译器中不以null结尾。这样我就可以创建一个(n)常量数组了。NUL终止的字符串是语言的固有属性。您可以使用字符数组,并逐个设置每个字符: char hex [] = {'0',

事实证明,这只是“c++不是c布鲁斯”的另一个例子


我想要什么

const char hex[16] = "0123456789ABCDEF";
唯一有效的方法

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

是否有任何编译器选项或我可以做的事情,使字符串在gcc编译器中不以null结尾。这样我就可以创建一个(n)常量数组了。NUL终止的字符串是语言的固有属性。您可以使用字符数组,并逐个设置每个字符:

char hex [] = {'0', '1', '2', ... 'F'};

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

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

§6.7.8p14

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


你回答了你自己的问题。如果显式为数组指定长度,如中所示:

const char hex[16] = "0123456789ABCDEF";
当然,它不会被空终止,因为没有为空终止保留的存储。(
hex[16]
在对象的边界之外,因此读取或写入它是未定义的行为。如果它恰好读取为0,则这是UB表示ya…)

只有将长度保留为隐式,如:

const char hex[] = "0123456789ABCDEF";
或者,如果将字符串文字用作对象而不是初始值设定项,则它将具有null终止


顺便问一下,如果您不打算使用它,为什么您会关心空终止是否存在呢。您正在尝试从二进制文件中删除字节吗?:-)

我认为这个问题有点不清楚:在C中,qoted初始化:

static const char hex[16] = "0123456789ABCDEF";
这是合法的。在C++中,它不是。因此,它是一个代码块,当从C到C++时,它会失败(幸运的是在编译时)。 如果有一种方法可以在不终止\0字节的情况下强制字符串文本,那就太好了。比如:

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

这里的
\!结尾处的0
告诉编译器不要为零终止字符串<代码>\甚至
\!0
字符串中的任何其他位置都不会被修改,因此只需输出一个文本
!0

在C++17中,实际上有一个部分解决此问题的方法:
constepr
函数可以返回类型为
std::array
的对象。所以,我们不是初始化const C数组,而是初始化了一个conExpRC++ ++代码:STD::数组< /COD>。此模板函数用于剥离终止符:

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 inline std::数组条带终止符(const CHAR(&in)[N])
{
std::数组输出{};
for(无符号长i=0;i
可按如下方式使用:

constexpr std::array<char, 16> hex = strip_terminator("0123456789ABCDEF");
constepr std::array hex=strip_终止符(“0123456789ABCDEF”);

所有操作都是在编译时完成的,即使关闭了优化:数组
hex
成为所需大小和所需内容的常数,没有多余的零终止字节。

回答得好。请注意,OP似乎对声明正好16个字节的数组感兴趣,因此在您的示例中包含数组大小说明符可能会有所帮助…
const char hex[16]={0',1',2',…'F'}它们可能是内在的,但根据标准,如果字符串不适合,编译器不能NUL终止字符串。没有必要像你所写的那样逐字解析它,因为它已经不是ONL以OP的方式终止了。@ SieEX:在我发布答案的时候,这个问题没有C++的TAG。我提到的标准是“C99”标准,但它也应该适用于ANSI C。+1,你的答案比我的好,因为它引用了标准。:-)应该注意到,C++中的这一点与C++中的不同,这就要求使用字符串文字的字符数组初始化器必须附加“0”-好(?)新闻是如果编译代码时,它会产生编译时错误,如果你需要C++和C++中的工作,你需要使用Walyk的解决方案。@ GLASHOTHOST。如果你问C++中是否将数组标记为代码> Extn(C)可能会有帮助,恐怕不行,我有个问题。我已经编写了一个程序,其中我将char数组初始化为一个字符串(逐字符,并在方括号中给出大小),然后打印它。但这不会导致错误,因为数组不是以null结尾的。为什么会发生这种情况?@R:空终止可能是一个问题,这是C语言中的一个抽象泄漏,因此不可避免。在其他语言中,可以简单地定义一个仅允许值0..15的类型,并使用该类型作为数组索引。这将防止已定义数组的溢出。这将使每个人的生活类型陷入地狱。一种语言(甚至是一个库)的类型越多,就越难正确使用。另一个例子说明了为什么你不应该在一个问题上同时加上“c”和“c++”。这里的答案肯定取决于你使用的语言。(参见C++ 03标准C.1.6[85.2])@为什么AcchPulter为什么为什么C++变成了“C类”以外的东西为什么不使用char HEX[] =“012345 67 89ABCDEF”?双引号使得编译器将输入作为零终止字符串。如果您想要16个随机字符(可能包含也可能不包含文字0),请不要使用双引号。