我正在使用指针并尝试不同的东西。
所以我在这里制作了一般的打印功能
void print(const int &value)
{
cout << "value = " << value << " & address = " << &value << endl;
}
现在,这是一个以某种方式运作的代码:
int j = 9090;
int* p;
*p = j; //Please read further
print(*p);
我知道* p = j是不合逻辑的,我应该做p =&amp; j或p = new int等......但为什么这样做呢? 输出是
value = 9090 & address = 0x28ff48
此外,如果我打印j,地址是0x28ff44。这意味着它为p自动分配了新的内存(因为它的地址是..48)
现在,如果我只在j&#39; s声明之前添加另一行:
int i = 80;
int j = 9090;
int* p;
*p = j; //Please read further
print(*p);
^程序崩溃。
但是,如果我在声明p之后添加这个我的行,程序就会运行。
int j = 9090;
int* p;
int i = 80;
*p = j;
print(*p);
我做错了吗?我在Dev C ++ IDE 4.9.9.2中使用GCC编译器。发生了什么事?
答案 0 :(得分:4)
问题是解除引用未初始化的指针是 undefined 。
这意味着任何事情都可能发生 - 有时程序会崩溃,有时会产生奇怪的结果,有时候(如果你不幸)它似乎会起作用。
由于您的指针未初始化,您将在其恰好代表的任何随机位置访问内存 有时,这是一个有效的地址,程序将继续运行 有时,它是一个无效的地址,程序会崩溃。
答案 1 :(得分:1)
int* p;
*p = j;
这是C ++的正确语法。这意味着在地址是p的字段中,你输入j的值。崩溃的问题源于你不为p提供任何记忆的事实。当你说int * p时,它意味着你有int变量的指针。但是,您没有在内存中提供任何实际地址来存储int值。 p中有一些垃圾,但这个垃圾被程序认为是有效的地址,它试图在那里写出j的值。如果你很幸运并且没有使用这个地址,程序将会更进一步。否则会崩溃。要避免这种未定义的行为,您需要为p:
分配内存int* p = new int;
*p = j;
答案 2 :(得分:1)
我知道* p = j是不合逻辑的
在这种情况下,它是未定义的行为。您正在取消引用未初始化的指针,因此它有效地指向未知(随机)位置。
这意味着它为p
自动分配了新内存
不,它没有。您看到的地址只是随机的,未定义的值,最终会出现在未初始化的指针中。
为什么这样做?
这是未定义行为的事情:它可能是巧合,例如,如果指针中的随机值碰巧指向某个有效的可写内存区域,那么您的代码将适用于该特定运行。还有一次,它可能会崩溃。还有一次,它可能会破坏你的堆或一些不相关的数据,并在一段时间之后导致看似无关的崩溃或错误。这只是在你的调试器前面长时间尖叫;)
底线:不要这样做 - 不惜一切代价避免使用UB。
然而,如果我在声明p之后添加这个我的行,程序就会运行。
我认为您观察到的行为(崩溃与不崩溃)与代码更改没有直接关系,但巧合。事实上,如果你多次运行“工作”版本,我肯定你会在一段时间后崩溃。