我正在学习指针。我在教程中看到了这个代码示例。我试过了,但它给出了与教程不同的结果。
#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上的"预期"行为。教训是:不要写这样的代码;)