Hello stackoverflow社区,我正在学习C ++中的指针。我在golang和python中有一些背景但在C或C ++中没有,所以请原谅我,因为我的理解有缺陷。让我发布一段正常工作的代码并给出段错误。
这个打印5
int var = 5;
int *p = &var;
cout << *p << endl;
这个也打印5
int *p;
p = &var;
cout << *p << endl;
打印5
(因为p是指向int的指针,var的地址是指向int的指针。)。
然而,
这一段错误。
int *p;
*p = var;
cout << *p << endl;
我认为是因为我将一个整数变量赋给一个变量,该变量应该是一个指向整数的指针。为什么在编译时没有显示不兼容的类型错误而不是给出分段错误?尝试这样做的程序是什么,给出了分段错误,以及如何?
和
这个也是段错误
int *p;
*p = 5;
cout << *p << endl;
也会引发段错误。我对上面代码的理解是,我声明了一个指向int的指针,并且我将一个整数值赋给一个取消引用的整数指针,但由于该变量未初始化,编译器还没有在堆栈上分配内存用于存储值(类似于悬空指针行为?)如果这是原因,为什么它会引发分段错误,该错误的原因是访问程序范围之外的内存?
谢谢。
答案 0 :(得分:3)
为什么它在编译时没有显示不兼容的类型错误 而不是给出分段错误?
因为类型兼容。 *p
的类型为int
,var
的类型为int
。你在这里处理的是运行时的问题,而不是在编译时。
尝试这样做的程序是什么,给出了分段错误, 怎么样?
*
运算符取消引用指针。这意味着,将获取该指针的地址,并检索该地址的内容。
在您的错误情况下,您将指针未初始化。因此,取消引用操作失败,因为引用的地址是不确定的。
如果仅声明变量而未初始化变量,编译器是否完全忽略变量名称并将其视为a 不存在的变量名?
完全没有。声明将名称引入特定范围。在您的示例中,您有 definitions :他们告诉编译器为它们分配一定的空间。
答案 1 :(得分:1)
创建指针时,它包含一些垃圾地址。当您尝试取消引用并写入某些值时,您已导致未定义的行为。
您必须在堆栈上分配一些现有变量的地址或在堆上分配内存,然后您可以取消引用它
就像你在前两个例子中所做的那样。您还可以在堆上分配一些内存,并将该内存的地址分配给指针
int *ptr = new int;
现在你可以取消引用这个指针(假设没有抛出bad_alloc异常),并为指针所指向的内存赋值。
答案 2 :(得分:1)
在上一篇文章中,你曾写过:
int *p;
*p = 5;
cout << *p << endl;
但在这种情况下,您尚未为p指定值。在使用之前,必须为指针赋值。你可以尝试如下:
int *p;
p = &var; //or another address of integer variable
*p = 5;
cout << *p << endl;
简而言之,我想强调一下,在使用之前必须为指针赋值。