c-相同的源代码,但在不同的操作系统上产生不同的结果



我正在学习指针。我在教程中看到了这个代码示例。我试过了,但它给出了与教程不同的结果。

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i = 5;
    int myInt = 7;
    int *pointer = &i;
    printf("%in", *(pointer + 1));
    return 0;
}
  • 在windows机器上,输出为2686740

  • 在linux机器上,输出为7。

这是什么原因?

为了详细说明现有的答案,我想添加一个解释。

在您的代码中,i是一个int变量。您将i的地址分配给pointer。好的然后,您要做的是增加指针(地址),然后尝试取消引用它

现在,与代码中的语句相比,

printf("%in", *(pointer + 1));    

引用C11标准,第6.5.6章,加法运算符

[….]如果两个指针操作数和结果指向同一数组对象的元素,或最后一个数组对象之后的元素数组对象的元素,则评估不应产生溢出;否则行为未定义如果结果指向数组对象的最后一个元素,则不应用作评估的一元*运算符的操作数

从本质上讲,通过这样做,您试图访问一些未分配给进程的内存,从而调用未定义的行为。

UB的输出是,嗯,未定义

内存(本例中为堆栈)类似于

[ i ][ something else .... 
^    ^
^    pointer+1 
pointer

进行

int *pointer = &i;
printf("%in", *(pointer + 1));

您显示一个int,即sizeof(int)pointer+1的内存空间被读取为int,这是编译器不希望您这样做的,并且该空间是"未知的"。所以Windows可能会显示X,Linux也可能会这样做,显示其他东西,甚至崩溃。。。

这是未定义的行为。

您正在对一个未分配给该指针/引用的区域进行指针运算,因此它是未定义的。它可以按照编译器的意愿来实现。

实际原因是在linux上,变量my int位于地址&i+1,而在windows上。。。它在其他地方

我认为代码对内存布局进行了假设,这些假设可能成立,也可能不成立。假设是:堆栈是线性的,变量完全按照源中声明的方式存储。这在某种程度上意味着您假定编译器不会进行任何优化。

在windows上尝试以下操作:(i)关闭编译器的所有优化,(ii)或在调试模式下运行。该行为可能会也可能不会切换到windows上的"预期"行为。教训是:不要写这样的代码;)

相关内容

  • 没有找到相关文章

最新更新