我目前正在努力通过"C++入门“。在其中一个练习问题中,它提出:
下面的程序是做什么的?
const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp)
{
cout << *cp << endl;
cp++;
}
我很高兴我理解*cp将继续是ca[]数组的最后一个字符,因为数组中没有空字符作为最后一个项。
这更多的是因为我自己的好奇心,是什么使时间循环成为错误的。它似乎总是在我的电脑上显示19个字符。0-4是hello字符串,5-11总是相同的,12-19随每次执行而改变.
#include <iostream>
using namespace std;
int main( )
{
const char ca[ ] = { 'h', 'e', 'l', 'l', 'o'/*, '\0'*/ };
const char *cp = ca;
int count = 0;
while ( *cp )
{
// {counter} {object-pointed-to} {number-equivalent}
cout << count << "\t" << *cp << "\t" << (int)*cp << endl;
count++;
cp++;
}
return 0;
}
问题:是什么导致while循环失效?为什么5-11总是同一个角色?
发布于 2016-08-13 10:45:07
因为对于语言来说,访问超出其界限的数组所发生的事情是没有定义的,如果您想了解发生了什么,您必须了解您的“平台”是如何工作的。
对于大多数编译器来说,您的内存可能是按如下方式排列的:
|H|e|l|l|o|XXX|____cp___|__count__|
XXX是对齐8所必需的“填充字节”。编译器-in调试版本--通常用除0以外的固定值填充这些字节,这样才不会停止(这样您就可以发现它)。
cp是一个指向"H“的指针,它一个接一个地递增。它的值通常是进程本身中进程堆栈的地址映射。
这个地址通常有一个固定的前缀,并且随着嵌套调用的深入,偏移值也会增加。
由于指针的长度(可能)为8字节(最后4个字节放在第一个字节之前,因为x86处理器的枚举数较低),您得到的是一个打印出来的迭代:
cp
偏移量(总是相同的,因为main总是在与程序本身相同的位置)这个前缀可能在某个点包含一个"0“,从而终止循环。
请注意,-however这个解释是有意义的--对于为不同平台编译的产品代码,您无论如何都不能信任它,甚至可能是不同的编译器,因为它们管理变量的方式也可能不同。
发布于 2016-08-13 09:39:44
C++允许您通过一个过去的ca[4]
(包含)创建指向ca[0]
的指针。不过,您可以取消引用(即应用操作符*
),仅通过ca[4]
对指向ca[0]
的指针进行引用;指向过去ca[4]
的指针是不允许的。当您取消引用指针时,会发生什么是未定义的行为。程序可能产生任何数据,甚至崩溃。
现实中发生的事情更简单:指针只是一个进入内存的地址,因此取消引用会继续向程序传递数字。在某个时候,地址包含一个零字节。这是你的程序停止的时候。
您的数组在自动内存中分配。大多数编译器都使用CPU堆栈。字节5.20的内容很可能包括cp
和count
,因为编译器倾向于将局部变量放在一起。之间可能有一些填充,因为指针和int
通常在可被4整除的地址对齐。当然,您不能指望任何这样的情况发生,因为其他编译器会采取不同的做法。
发布于 2016-08-13 09:36:20
重要的是要知道,您正在体验Undefined behavior
。因此,无论您现在看到什么,当您使用不同的编译器或不同的编译器选项时,都可能会有所不同。
5-11上的“常量”值最能解释的原因是,您正在读取堆栈的一部分,而该部分每次都恰好具有相同的值。
https://stackoverflow.com/questions/38931288
复制相似问题