相同的源代码,但不同操作系统上的结果不同
我正在学习指针。我在教程中看到了这个代码示例。我试过了,但它给了教程不同的结果。相同的源代码,但不同操作系统上的结果不同
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i = 5;
int myInt = 7;
int *pointer = &i;
printf("%i\n", *(pointer + 1));
return 0;
}
在Windows机器上,输出为2686740
一台Linux机器上,输出为7
,这是什么原因呢?
内存(堆栈在这种情况下)的地方是这样的
[ i ][ something else ....
^ ^
^ pointer+1
pointer
否则
int *pointer = &i;
printf("%i\n", *(pointer + 1));
你显示一个int,即从sizeof(int)
pointer+1
存储器空间被读取为一个int
,这是编译器不希望你做的事情,而且这个空间是“未知的”。所以Windows可能会显示X,Linux也可能会这样做,显示其他内容甚至崩溃...
这是未定义的行为。
您正在将指针运算放入未分配给该指针/引用的区域,因此未定义。然而编译器希望它可以被实现。
实际的原因是,在Linux上,可变我INT位于地址& + 1,而在窗户......这是别人
我认为代码正在对可能或不可能适用的内存布局做出假设。假设是:栈是线性的,变量的存储与源中声明的完全相同。这意味着你会假设编译器不做任何优化。
在Windows上尝试以下操作:(i)关闭编译器的所有优化,(ii)或在调试模式下运行。行为可能会或可能不会切换到Windows上的“预期”行为。教训是:不写这样的代码;)
为了详细说明现有的答案,我想补充一个解释。
在您的代码中,i
是一个int
变量。您将i
的地址分配给pointer
。精细。然后,你要做的是,增加指针(地址),然后试图解引用它。现在
,在比较声明在你的代码,
printf("%i\n", *(pointer + 1));
引述C11
标准,章§6.5.6,加法运算符
[....]如果指针 的操作数和结果指向同一个数组对象的元素,或者数组对象的最后一个 元素,则评估不应产生溢出;否则, 行为未定义。 如果结果指向数组对象的最后一个元素之后,则不应将其作为被评估的一元运算符
*
的操作数使用。
从本质上讲,这样做,你要访问没有分配给你的进程,从而调用undefined behavior一些内存。
UB的输出是undefined。
感谢您的解释,并分享了我以前不知道的参考资料。 –
@Hakan不用客气。 :) –
查找'未定义的行为'。在'*(pointer + 1)'处没有特别的保证,因为代码从不分配或保留任何东西。另外,请指出“教程”,以便其他人知道避免它。 – dxiv
访问无效内存是未定义的行为。更多细节:[“未定义的行为”是否真的允许*发生任何事情?](https://*.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen)和[Undefined ,未指定和实现定义的行为](https://*.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior)。 – kaylum
@dxiv我不知道这是不是一个错误的教程。事实上,我是一个绝对的初学者。 [link] https://youtu.be/5jQ2ZiXzJjE?t=3m57s –