C 不带'的字符串\0';烧焦

C 不带'的字符串\0';烧焦,c,string,C,String,如果我错误地定义了一个字符数组,其中没有\0作为最后一个字符,那么会发生什么 我问这个问题是因为我注意到如果我尝试用遍历数组,而(cnt!='\0'),其中cnt是用作数组索引的int变量,同时打印cnt值以监控发生的情况迭代在最后一个字符+2处停止。额外的字符当然是随机的,但我无法理解为什么必须在2之后停止。编译器是否自动插入\0字符?如能链接到相关文件,将不胜感激 为了说明这一点,我举了一个例子。假设数组str包含单词doh(没有'\0')。在每个循环中打印cnt变量会得到以下结果: doh

如果我错误地定义了一个字符数组,其中没有
\0
作为最后一个字符,那么会发生什么

我问这个问题是因为我注意到如果我尝试用
遍历数组,而(cnt!='\0')
,其中
cnt
是用作数组索引的int变量,同时打印cnt值以监控发生的情况迭代在最后一个字符+2处停止。额外的字符当然是随机的,但我无法理解为什么必须在2之后停止。编译器是否自动插入
\0
字符?如能链接到相关文件,将不胜感激

为了说明这一点,我举了一个例子。假设数组
str
包含单词
doh
(没有'\0')。在每个循环中打印cnt变量会得到以下结果:
doh+
doh^

以此类推。

如果碰巧
*(str+5)
处的字节是
0
(作为一个数字,而不是ASCII)

如果您定义的字符数组没有终止符
\0
(称为“空终止符”),那么您的字符串将没有该终止符。你可以这样做:

char strings[] = {'h', 'e', 'l', 'l', 'o'};
在这种情况下,编译器不会自动插入空终止符。您的代码在“+2”之后停止是一个巧合;根据字符串后面的内存中是否碰巧有\0个字符,它可以很容易地在+50或其他任何位置停止

如果将字符串定义为:

char strings[] = "hello";
那么这将确实是空终止的。当使用C中的引号时,即使在文本编辑器中看不到它,字符串的末尾也会有一个空终止符

有些与C字符串相关的函数会自动附加空终止符。这不是编译器所做的事情,而是函数规范本身的一部分。例如,将一个字符串连接到另一个字符串,将在末尾添加空终止符


但是,如果您使用的其中一个字符串没有终止符,那么该函数将不知道字符串的结束位置,您将得到垃圾值(或分段错误)。

就大多数字符串处理函数而言,字符串总是在
'\0'
字符处停止。如果您在某个地方错过了此空终止符,通常会发生以下三种情况之一:

  • 您的程序将继续读取字符串的末尾,直到找到刚好在那里的
    '\0'
    。有几种方法可以让这样的字符出现,但它们中没有一种通常是事先可以预测的:它可能是另一个变量的一部分、可执行代码的一部分,甚至是先前存储在同一缓冲区中的较大字符串的一部分。当然,到那时,程序可能已经处理了大量的垃圾。如果看到由
    printf()
    生成的大量垃圾,则未终止的字符串是常见原因

  • 您的程序将继续读取字符串的末尾,直到它尝试读取其地址空间之外的地址,从而导致内存错误(例如,Linux系统中可怕的“分段错误”)

  • 在字符串上复制时,程序将耗尽空间,并再次导致内存错误


而且,不,C编译器通常只执行您在程序中指定的操作——例如,它不会自行终止字符串。这就是为什么C如此强大,也很难编写代码的原因。

我打赌int是在字符串之后定义的,并且该int只接受较小的值,因此至少有一个字节是0。

编辑(未定义的行为)

访问数组边界之外的数组元素是未定义的行为。
用C字符串以外的任何东西调用字符串函数都是未定义的行为。
别这样

C字符串是以结尾的字节序列,包括
'\0'
(NUL终止符)。所有字节必须属于同一对象


不管怎样,你看到的只是巧合

但它可能会这样发生

,------------------ garbage | ,---------------- str[cnt] (when cnt == 4, no bounds-checking) memory ----> [...|d|o|h|*|0|0|0|4|...] | | \_____/ -------- cnt (big-endian, properly 4-byte aligned) \___/ ------------------ str ,--------------垃圾 |,------------str[cnt](当cnt==4时,无边界检查) 内存-->[…|d|o|h*| 0 | 0 | 0 | 4 |] || \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu \___/---------str 在C语言中,术语字符串指以零结尾的字符数组。所以,从学究的角度讲,没有“没有'\0'字符的字符串”这样的东西。如果不是以零结尾,则它不是字符串


现在,只要你明白它不是一个字符串,那么仅仅拥有一个没有零的字符数组并没有什么错。如果您试图像处理字符串一样处理这样的字符数组,则程序的行为是未定义的。任何事情都有可能发生。出于某些神奇的原因,它似乎“起作用”。或者它可能会一直崩溃。实际上,这样一个程序会做什么并不重要,因为如果行为没有定义,程序就没有用。

@kaiseroskilo:concurrence,或者相邻变量的一个字节的实际值。未明确初始化的内存可能包含任何值,零是很常见的。