我正在阅读 Stephen Prata 的 C++ Primer Plus。他举了这个例子:
char dog[8] = { 'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string!
char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // a string!
评论说:
这两个数组都是 char 数组,但只有第二个是字符串。空字符在 C 风格的字符串中起着基本作用。例如,C++ 有许多处理字符串的函数,包括 cout 使用的函数。它们都通过逐个字符处理字符串直到它们到达空字符来工作。如果您要求 cout 在前面的示例中显示类似 cat 的漂亮字符串,它会显示前七个字符,检测到空字符并停止。但是,如果您不礼貌地告诉 cout 显示前面示例中的 dog 数组,它不是字符串,cout 会打印数组中的八个字母,然后逐字节继续在内存中前进,将每个字节解释为要打印的字符,直到它到达一个空字符。因为空字符,实际上是设置为零的字节,往往在记忆中很常见,损害通常很快被遏制;尽管如此,您不应将非字符串字符数组视为字符串。
现在,如果将我的变量声明为全局变量,如下所示:
#include <iostream>
using namespace std;
char a[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
char b[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
int main(void)
{
cout << a << endl;
cout << b << endl;
return 0;
}
输出将是:
abcdefgh12345678
12345678
因此,确实, cout “继续逐字节地在内存中前进”,但只到第二个字符数组的末尾。char 数组的任何组合都会发生同样的事情。我在想所有其他地址都初始化为 0,这就是 cout 停止的原因。这是真的?如果我这样做:
for (int i = 0; i < 100; ++i)
{
cout << *(&a + i) << endl;
}
我在输出时得到了大部分空白空间(可能是 95%),但不是到处都是。
但是,如果我声明我的 char 数组更短一些,例如:
char a[3] = {'a', 'b', 'c'};
char b[3] = {'1', '2', '3'};
保持所有其他事情相同,我得到以下输出:
abc
123
现在 cout 甚至没有通过第一个 char 数组,更不用说第二个了。为什么会这样?我检查了内存地址,它们是连续的,就像在第一个场景中一样。例如,
cout << &a << endl;
cout << &b << endl;
给
003B903C
003B9040
为什么在这种情况下行为不同?为什么它不读取第一个字符数组之外的内容?
最后,如果我确实在 main 中声明了我的变量,那么我确实得到了 Prata 建议的行为,即之前打印了很多垃圾,某个地方到达了一个空字符。
我猜在第一种情况下,char 数组是在堆上声明的,并且它被初始化为 0(但不是到处都是,为什么?)并且 cout 的行为会根据 char 数组的长度而有所不同(为什么?)
我将 Visual Studio 2010 用于这些示例。