mih*_*hai 1 c++ arrays string visual-studio-2010
我正在阅读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!
Run Code Online (Sandbox Code Playgroud)
评论:
这两个数组都是char数组,但只有第二个是字符串.null字符在C风格字符串中起着基本作用.例如,C++有许多处理字符串的函数,包括cout使用的函数.它们都是通过逐个字符处理字符串直到它们到达空字符.如果你要求cout在前面的例子中显示像cat这样的好字符串,它会显示前7个字符,检测空字符并停止.但是,如果你有足够的语言来告诉cout显示前面例子中的狗数组,这不是一个字符串,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;
}
Run Code Online (Sandbox Code Playgroud)
输出将是:
abcdefgh12345678
12345678
Run Code Online (Sandbox Code Playgroud)
所以,确实,cout"逐字节地继续行进",但仅限于第二个字符数组的末尾.任何char数组的组合都会发生同样的事情.我想所有其他地址都被初始化为0,这就是cout停止的原因.这是真的?如果我这样做:
for (int i = 0; i < 100; ++i)
{
cout << *(&a + i) << endl;
}
Run Code Online (Sandbox Code Playgroud)
我输出的空间大部分都是空的(也许是95%),但不是到处都是.
但是,如果我声明我的char数组有点短,例如:
char a[3] = {'a', 'b', 'c'};
char b[3] = {'1', '2', '3'};
Run Code Online (Sandbox Code Playgroud)
保持所有其他东西相同,我得到以下输出:
abc
123
Run Code Online (Sandbox Code Playgroud)
现在cout甚至没有超过第一个char数组,更不用说第二个了.为什么会这样?我检查了内存地址,它们是顺序的,就像在第一个场景中一样.例如,
cout << &a << endl;
cout << &b << endl;
Run Code Online (Sandbox Code Playgroud)
给
003B903C
003B9040
Run Code Online (Sandbox Code Playgroud)
为什么在这种情况下行为会有所不同?为什么它不读取第一个char数组?
而且,最后如果我确实在main中声明了我的变量,那么我确实得到了Prata建议的行为,即之前很多垃圾被打印出来,某处达到空字符.
我猜测在第一种情况下,char数组在堆上声明并初始化为0(但不是到处都是,为什么?)和cout根据char数组的长度表现不同(为什么?)
我在这些示例中使用Visual Studio 2010.
小智 5
看起来您的C++编译器正在以4字节块的形式分配空间,因此每个对象的地址都是4的倍数(转储中的十六进制地址可被4整除).编译器喜欢这样做是因为他们希望确保更大的数据类型(例如int和float(4字节宽))与4字节边界对齐.编译器喜欢这样做,因为某些类型的计算机硬件需要更长的时间来加载/移动/存储未对齐的值int和float值.
在您的第一个示例中,每个数组需要8个字节的内存 - char填充单个字节 - 因此编译器恰好分配8个字节.在第二个例子中,每个数组是3个字节,因此编译器分配4个字节,用你的数据填充前3个字节,并保留第4个字节未使用.
现在在第二种情况下,看起来未使用的字节用空填充,这解释了为什么cout停止在字符串的末尾.但正如其他人所指出的那样,您不能依赖未使用的字节来初始化为任何特定值,因此无法保证程序的行为.
如果将样本数组更改为4个字节,则程序的行为与第一个示例相同.