只是因为你可以对某些任意地址执行指针算术并不意味着你应该。 C给你很大的灵活性去做你想做的事,但这也意味着它相信你做正确的事情,你不是。
你试图做的是写入一个内存地址sizeof(int)
字节超过地址a
。该内存地址不是a
的一部分,写入它将调用undefined behavior。
至于你的具体情况发生了什么,局部变量通常存储在大多数托管实现的堆栈中。所以如果你写过一个变量的边界,你很可能会覆盖相邻变量或函数的返回地址。鉴于你的程序崩溃了,你可能正在做后者。
这里的覆盖另一个变量的说明:
#include <stdio.h>
int main(void)
{
int before = 0;
int a = 1;
int after = 0;
int * arr1 = &a;
*(arr1 + 1) = 2;
printf("%d %d\n", *arr1, *(arr1+1));
printf("before=%d, after=%d\n", before, after);
}
在这个例子中,我把你的例子,之前和之后a
加入一个变量。当我运行它,我得到以下的输出:
1 2
before=2, after=0
你可以看到,before
现在设置为2,即使它没有明确设置。这意味着它出现在a
之后的堆栈中。所以通过编写一个过去的a
,你最终会写入before
。
重申,这是未定义的行为。编译器可以按任意顺序排列堆栈上的变量。例如,如果您要添加额外的printf
调用或使用不同的优化设置进行编译,您可能会得到不同的结果。我用-O1
重新编译了上面的代码,并运行它导致了核心转储。
因此,如果需要特定数量的内存,并且没有明确预留空间,则需要拨打malloc
以获取所需的内存。然后你可以自由地读取和写入该块。
这是未定义的行为。 – BLUEPIXY
虽然技术上*未定义的行为*,但最可能的是您正在写入不属于您的堆栈内存。这可能表现为另一个本地变量或函数参数获取更改的值。或者你因为函数的返回地址被破坏 - 或者更糟 - 当函数返回时在指令指针的其他位置结束而崩溃。 – selbie
你需要更多的基本概念研究。你的头衔反映了根本的误解。使用'malloc'进行堆分配预留存储空间供程序使用。您的程序可以使用指针算术来读取和写入已经保留的存储中的值。得到一本好书。 – Gene