我编写了类似下面代码的东西,并且我能够在增加它之后为新地址分配一个值,但是无法打印此值run time error
。此外,在为该指针指向的位置赋值后,指针值更改为是14.任何人都知道发生了什么事?
在为位置本身赋值后,为什么指针值本身会更改为14?
增加指针值后我没有收到任何错误!
#include <stdio.h>
int main()
{
int x = 10;
int *ptr = &x;
printf("%x\n",ptr); // ptr value
ptr++; //No ERROR !!
printf("%x\n",ptr); //ptr value +4 bytes no error!!!
*ptr = 20;
printf("%x\n",ptr); //ptr=14
printf("%x\n",*ptr); // run time error happens here only
return 0;
}
当你做ptr++
时,它指出“一个元素”超过x
。这是允许的,因为在这种情况下x
被视为大小为1的数组,并且允许指针指向一个元素超过数组的末尾。您也可以随后打印该指针的值,没有任何问题。
然而,你不能做的是取消引用一个指向一个元素的指针。这会引发undefined behavior。在这种情况下,该行为表现为指针具有意外值和随后的崩溃。
话虽如此,这可能发生了什么。
ptr
很可能是在x
记忆之后,所以在做了ptr++
之后,ptr
指向自己。所以*ptr = 20;
具有将ptr
设置为20的效果。打印的值14是十六进制,与20十进制相同。这解释了打印的价值。
然后你试图打印*ptr
,在这种情况下说“打印地址0x14处的int
值”。这很可能不是一个有效的地址,因此尝试阅读它会导致崩溃。
但是,您无法依赖此行为。您可以添加额外的printf
或使用不同的优化设置进行编译,并且观察到的行为会发生变化。
这是未定义的行为。当你增加指针变量时,它指向一个超过变量x
(系统中4字节过去)的变量。但是你取消引用它。首先,您更改的内存不是由您分配的。而且它不是已经分配的位置(如数组的一部分等)。访问它是未定义的行为。
您可以再次将其分配给任何可能的地址。但是,如果它指向的内存地址无效,则取消引用它将是未定义的行为。
从标准6.3.2.3
一元
*
算子表示间接。如果操作数指向函数,则结果是函数指示符;如果它指向一个对象,则结果是指定该对象的左值。如果操作数的类型为''pointer to type''
,则结果为type
。如果为指针指定了无效值,则unary*
运算符的行为未定义