不为null终止C样式字符串

时间:2012-09-17 16:15:29

标签: c string c-strings

给出一个字符串,比方说,

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-string的最后一个字符必须是'\0',因为这里我们没有明确地做同样的事情(在字符串newStr的最后一个索引处存储'\ 0'),这个程序应该崩溃,因为printf将找不到字符串的结尾。

但是我注意到它有时工作得很好,有时却没有。可能是什么问题呢 ?它几乎每次都在工作。是不应该崩溃或给出一些运行时错误?

C ++中也会出现同样的情况吗?

6 个答案:

答案 0 :(得分:6)

没有。它会调用未定义的行为 - 这意味着它不会崩溃 - 它可以做任何事情,例如nasal demons.

此外,“给出运行时错误” - 这取决于运行时错误的含义。 C没有动态运行时 - 如果您期望异常的格式错误消息,则不会发生。会发生什么情况最有可能是segmentation fault.

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

答案 1 :(得分:3)

“崩溃”保证。不正确地处理字符串中的空终止符的程序 - 更通常是访问缓冲区边界之外的数据 - 或者违反printf格式字符串,可能看起来很好,功能正常,而不是导致段错误。但这只是偶然事件:代码的行为未定义。

在C ++中也是如此。

答案 2 :(得分:2)

我怀疑大多数时候它会继续印刷“!”并继续在内存中,直到它达到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 ++ )

正如defination of strlen暗示你需要的那样。

答案 3 :(得分:1)

偶然地,大部分时间 newStr中未初始化的字节恰好是0

答案 4 :(得分:1)

您的程序有未定义的行为,因为您承诺使用指向以null结尾的字符串的指针调用printf但未能这样做。任何事情都可能发生,但你的程序根本不正确。

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

答案 5 :(得分:0)

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

(也就是说,如果你的程序会编译 - 你已经没有分号了)