#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
a=&c;
*b=*b;
cout << *b << endl;
}
上面的代码工作正常,但是下面的代码返回分段错误错误
#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
//a=&c;
*b=*b;
cout << *b << endl;
}
为什么?
gcc(Ubuntu 8.2.0-7ubuntu1)8.2.0
答案 0 :(得分:4)
这是您的代码执行情况的分步细分:
format
这声明了两个指向int *a;
int *b;
和int
的指针a
。它不初始化它们。这意味着它们的值是不确定的,您应该期望它们是完全垃圾。您现在可以将它们视为“野生”指针,这就是说它们没有指向有效对象,并且对它们的取消引用将导致未定义行为,并且会引入大量奇怪的错误,即使不是简单的崩溃也是如此。 / p>
b
这将创建类型为int c=12;
的简单局部变量c
,该变量将初始化为 ,其值为int
。如果您没有像12
中那样初始化它,那么它也将充满垃圾。
int c;
此代码段将指针a=&c;
设置为指向a
,这就是说c
的地址已分配给c
。现在a
不再是未初始化的,并且指向定义明确的位置。之后,您可以安全地取消引用a
,并确保另一端有有效的a
。
int
在这里,您要取消引用*b=*b;
,这意味着您正在进入程序存储器以获取b
指向的内容。但是b
尚未初始化;这是垃圾。它指的是什么?谁知道?从它指向的地址中读取内容就像是俄罗斯轮盘赌,如果您真的很倒霉并且操作系统或运行时环境注意到您执行了明显错误的操作,则可能会立即杀死程序。但是您也可能会摆脱它,只是为了 weird 和后来出现的不可预测的错误。这种怪异和不可预测性是为什么优秀的C ++程序员不惜一切代价避免未定义行为,并确保变量在使用前已初始化,并确保指针在指向有效对象之前先解除引用。
为什么取决于b
会有区别?
根据您初始化另一个指针的方式,为什么程序显然崩溃或不崩溃,答案是没关系。在这两种情况下,您都将导致未定义的行为。您违反了该语言的规则,此后您不应指望该语言为您提供正确的行为,并且所有赌注都关闭了。
答案 1 :(得分:2)
“ *b=*b
”-代码损坏。 b
未初始化,因此您要取消引用未初始化的指针。那是不确定的行为。该程序已损坏,按照标准没有任何意义,并且允许编译器生成任何感觉的 代码(无需诊断)。