繁体   English   中英

不以N结尾的C样式字符串

[英]Not null-terminating a C-style string

给定一个字符串,说,

char *str = "Hello,StackOverflow!"
char newStr[30];
int l = strlen(str);
for(int i =0 ; i<l ; i ++ )
   newStr[i] = str[i];
printf("%s" , newStr);

现在,我们知道c字符串的最后一个字符必须为'\\0' ,因为在这里我们没有明确地执行相同的操作(将'\\ 0'存储在字符串newStr的最后一个索引中),所以该程序应该崩溃,因为printf找不到字符串的结尾。

但是我注意到它有时工作正常,有时却不行。 可能是什么问题呢 ? 实际上,它几乎每次都在工作。 它不是应该崩溃还是给出一些运行时错误?

在C ++中也会一样吗?

不会。它会引发未定义的行为-这意味着它不必崩溃 -它可以执行任何操作,例如鼻恶魔。

另外,“给出运行时错误”-好吧,这取决于您所表示的运行时错误。 C没有动态运行时-如果您期望异常产生格式正确的错误消息,则不会发生这种情况。 可能会发生分段错误。

总而言之,如果一个人导致/使用了未定义的行为,则他绝不能依靠它崩溃或崩溃。

不能保证“崩溃”。 一个不正确地处理字符串中的空终止符的程序-更普遍地访问缓冲区边界之外的数据-或违反了printf格式的字符串,该程序似乎可以正常运行,正常运行,并且不会引起例如段错误。 但这只是偶然:代码的行为是不确定的。

在C ++中将是相同的。

我怀疑大多数情况下它会一直打印超过“!” 并继续进入内存,直到它达到NULL。 可能会导致崩溃,但不必这样做。

这就是为什么最好执行以下任一操作的原因:

memset(newStr, 0, 30);

要么

// This works because string literals guarantee a '\0' is present
// but the strlen returns everything up until the '\0'
int l = strlen(str) + 1;

这也可以,但是我不觉得像在strlen中添加一个一样清晰:

for(i =0 ; i<=l ; i ++ )

正如strlen定义所暗示的,您需要这样做

偶然地,在您的特定情况下, 大多数时候 newStr的未初始化字节碰巧是0

您的程序具有未定义的行为,因为您答应使用指向以null终止的字符串的指针来调用printf ,但是这样做失败。 可能发生任何事情,但是您的程序根本不正确。

具体来说,在逐一读取数组元素以找到空终止符的同时,程序最终将访问未初始化的变量UB。

在大多数C的实现中,尚未读取未初始化为字符的字节的行为是不确定的。有时printf可能会写入垃圾,有时程序可能会在最后一个字符之后找到一个空字节\\ 0并正常终止。 在极少数情况下,它可能会导致崩溃。 这就是为什么您看到运行程序时会发生变化的原因。 这取决于您使用的编译器,以及在该数组中分配的内存位置之后的内存位置。

(也就是说,如果您的程序可以编译-您就不用分号了)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM