相同的源代码但在不同操作系统上的结果不同
Same source code but different result on different operating systems
正在学习指点。我在教程中看到了这个代码示例。我试过了,但它给出了与教程不同的结果。
#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。
这是什么原因?
您正在对未分配给 pointer/reference 的区域进行指针运算,因此它是未定义的。它可以按照编译器的意愿实现。
真正的原因是在linux上,变量my int位于地址&i + 1,而在windows...它在其他地方
内存(这里是栈)是这样的
[ i ][ something else ....
^ ^
^ pointer+1
pointer
正在做
int *pointer = &i;
printf("%i\n", *(pointer + 1));
你显示一个 int,即 sizeof(int)
的 pointer+1
的内存 space 被读取为 int
,编译器不希望你这样做,而 space 是 "unknown"。所以 Windows 可能会显示 X,Linux 也可能会显示 X,显示其他内容甚至崩溃 ...
这是未定义的行为。
我认为代码正在对可能成立或不成立的内存布局做出假设。假设是:堆栈是线性的,变量的存储与源代码中声明的完全相同。这在某种程度上暗示您假设编译器不进行任何优化。
在 windows 上尝试以下操作:(i) 关闭编译器的所有优化,(ii) 或 运行 在调试模式下。该行为可能会或可能不会切换到 windows 上的 "expected" 行为。教训是:不要写这样的代码;)
针对已有的答案进行阐述,我想补充说明。
在您的代码中,i
是一个 int
变量。您将 i
的地址分配给 pointer
。美好的。然后,您要做的是增加指针(地址),然后尝试取消引用它。
现在,与代码中的语句相比,
printf("%i\n", *(pointer + 1));
引用 C11
标准,第 6.5.6 章,加法运算符
[....] If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element of the array object, it
shall not be used as the operand of a unary *
operator that is evaluated.
本质上,通过这样做,您试图访问一些未分配给您的进程的内存,从而调用 undefined behavior.
UB 的输出,嗯,未定义。
正在学习指点。我在教程中看到了这个代码示例。我试过了,但它给出了与教程不同的结果。
#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。
这是什么原因?
您正在对未分配给 pointer/reference 的区域进行指针运算,因此它是未定义的。它可以按照编译器的意愿实现。
真正的原因是在linux上,变量my int位于地址&i + 1,而在windows...它在其他地方
内存(这里是栈)是这样的
[ i ][ something else ....
^ ^
^ pointer+1
pointer
正在做
int *pointer = &i;
printf("%i\n", *(pointer + 1));
你显示一个 int,即 sizeof(int)
的 pointer+1
的内存 space 被读取为 int
,编译器不希望你这样做,而 space 是 "unknown"。所以 Windows 可能会显示 X,Linux 也可能会显示 X,显示其他内容甚至崩溃 ...
这是未定义的行为。
我认为代码正在对可能成立或不成立的内存布局做出假设。假设是:堆栈是线性的,变量的存储与源代码中声明的完全相同。这在某种程度上暗示您假设编译器不进行任何优化。
在 windows 上尝试以下操作:(i) 关闭编译器的所有优化,(ii) 或 运行 在调试模式下。该行为可能会或可能不会切换到 windows 上的 "expected" 行为。教训是:不要写这样的代码;)
针对已有的答案进行阐述,我想补充说明。
在您的代码中,i
是一个 int
变量。您将 i
的地址分配给 pointer
。美好的。然后,您要做的是增加指针(地址),然后尝试取消引用它。
现在,与代码中的语句相比,
printf("%i\n", *(pointer + 1));
引用 C11
标准,第 6.5.6 章,加法运算符
[....] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary
*
operator that is evaluated.
本质上,通过这样做,您试图访问一些未分配给您的进程的内存,从而调用 undefined behavior.
UB 的输出,嗯,未定义。