我现在正在学习 C 与“C Programming Absolute Beginner's Guide”(第 3 版),其中写道所有字符数组的大小应等于 string length + 1
(这是 string -终止零长度)。但是这段代码:
#include <stdio.h>
main()
{
char name[4] = "Givi";
printf("%s\n",name);
return 0;
}
输出 Givi
而不是 Giv
。数组大小为 4
,在这种情况下它应该输出 Giv
,因为 4(字符串长度)+ 1(字符串终止零字符长度)= 5,并且字符数组大小仅为 4
。
为什么我的代码输出的是 Givi
而不是 Giv
?
我正在使用 MinGW 4.9.2 SEH 进行编译。
最佳答案
你击中了被认为是 undefined behavior 的东西.它现在正在工作,但由于偶然性,而不是正确性。
在你的情况下,这是因为你的程序中的内存可能在一开始就全部清零了。因此,即使您的字符串未正确终止,它之后的内存恰好为零,因此 printf
知道何时停止。
+-----------------------+
|G|i|v|i|\0|\0|... |
+-----------------------+
| your | rest of |
| stuff | memory (stack)|
+-----------------------+
其他语言(例如 Java)具有针对此类情况的保护措施。然而,像 C 这样的语言,手牵手的事情更少,一方面,它允许更多的灵 active ,但另一方面,给你更多的方式来解决诸如这个这样的微妙问题。换句话说,如果您的代码编译通过,那并不意味着它是正确的,并且它现在、5 分钟或 5 年后都不会崩溃。
在现实生活中,几乎从来没有这种情况,您的字符串最终可能会存储在其他东西旁边,而这些东西最终总是会与您的字符串一起打印出来。你永远不会想要这个。像这样的情况可能会导致崩溃、漏洞利用和 secret 信息泄露。
有关示例,请参见下图。想象一下,您正在使用 Web 服务器和字符串“secret”——用户的密码或 key 存储在您的无害字符串旁边:
+-----------------------+
|G|i|v|i|s|e|c|r|e|t |
+-----------------------+
| your | rest of |
| stuff | memory (stack)|
+-----------------------+
每次您输出您认为是“Givi”的内容时,您最终都会打印出 secret 字符串,这不是您想要的。
关于C字符数组及其长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30852420/