相同的源代码,但不同操作系统上的结果不同

问题描述:

我正在学习指针。我在教程中看到了这个代码示例。我试过了,但它给了教程不同的结果。相同的源代码,但不同操作系统上的结果不同

#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

,这是什么原因呢?

+3

查找'未定义的行为'。在'*(pointer + 1)'处没有特别的保证,因为代码从不分配或保留任何东西。另外,请指出“教程”,以便其他人知道避免它。 – dxiv

+0

访问无效内存是未定义的行为。更多细节:[“未定义的行为”是否真的允许*发生任何事情?](https://*.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen)和[Undefined ,未指定和实现定义的行为](https://*.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior)。 – kaylum

+0

@dxiv我不知道这是不是一个错误的教程。事实上,我是一个绝对的初学者。 [link] https://youtu.be/5jQ2ZiXzJjE?t=3m57s –

内存(堆栈在这种情况下)的地方是这样的

[ 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

+0

感谢您的解释,并分享了我以前不知道的参考资料。 –

+0

@Hakan不用客气。 :) –