C字符数组及其长度

vas*_*111 1 c c-strings

我现在正在用"C编程绝对初学者指南"(第3版)学习C,并且写了所有字符数组的大小应该等于string length + 1(字符串终止零长度).但是这段代码:

#include <stdio.h>
main()
{
    char name[4] = "Givi";
    printf("%s\n",name);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出Givi而不是Giv.数组大小是,4并且在这种情况下它应该输出Giv,因为4(字符串长度)+ 1(字符串终止零字符长度)= 5,并且字符数组大小是唯一的4.

为什么我的代码输出Givi而不是Giv

我正在使用MinGW 4.9.2 SEH进行编译.

And*_*san 7

你正在击中被认为是未定义的行为.它现在正在工作,但由于机会,不正确.

在你的情况下,这是因为程序中的内存可能在开始时全部归零.因此,即使你的字符串没有正确终止,它恰好在它之后的内存为零,因此printf知道何时停止.

+-----------------------+
|G|i|v|i|\0|\0|...      |
+-----------------------+
| your  | rest of       |
| stuff | memory (stack)|
+-----------------------+
Run Code Online (Sandbox Code Playgroud)

其他语言(如Java)可以防范这种情况.然而,像C这样的语言可以减少手握,这一方面可以提供更大的灵活性,但另一方面,给你更多,更多的方法来拍摄你的脚,有这样的微妙问题.换句话说,如果您的代码编译,这并不意味着它是正确的,并且它现在不会在5分钟或5年内爆炸.

在现实生活中,几乎从来没有这种情况,并且你的字符串可能最终会被存储在其他东西旁边,这总会最终与你的字符串一起打印出来.你永远不会想要这个.像这样的情况可能会导致崩溃,漏洞和泄露的机密信息.

有关示例,请参见下图.想象一下,您正在处理Web服务器和字符串"secret" - 用户的密码或密钥存储在无害字符串旁边:

+-----------------------+
|G|i|v|i|s|e|c|r|e|t    |
+-----------------------+
| your  | rest of       |
| stuff | memory (stack)|
+-----------------------+
Run Code Online (Sandbox Code Playgroud)

每当你输出你认为是"Givi"的东西时,你最终会打印出秘密字符串,这不是你想要的.