为什么变量的地址在这里发生变化?

Why is the address of the variable changing here?

提问人:Bemin Dawoud 提问时间:10/23/2023 最后编辑:CiaPanBemin Dawoud 更新时间:10/23/2023 访问量:94

问:

我正在尝试使用指针来更好地掌握它,我在这里遇到了这种情况: 我声明了一个变量 var 和两个指针。我正在打印 var 的地址以将其与两个指针进行比较,但即使语句相同,它也在两个值之间不断变化?

这是它第一次给出 var 的地址:0061FF1C

我使用的代码:

#include <stdio.h>
 
int main () {

   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;
   ptr = &var;
   pptr = &ptr;

   printf("Address of var = %p\n", &var );
   printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var
   printf("Address of ptr = %p\n", &ptr ); // should be equal to address of ptr
   printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr
   printf("address of pptr = %p\n", &pptr ); // should be equal to address of pptr
   return 0;
}

输出:

Address of var = 0061FF1C
Value available at ptr = 0061FF1C
Address of ptr = 0061FF18
value available at pptr = 0061FF18
address of pptr = 0061FF14

这是它第二次给出 var 的地址: 我使用的代码:0061FF18

#include <stdio.h>
 
int main () {

   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;
   ptr = &var;
   pptr = &ptr;

   printf("Address of var = %p\n", &var );
   printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var
   printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr

   return 0;
}

输出:

Address of var = 0061FF18
Value available at ptr = 0061FF18
value available at pptr = 0061FF14

我期望 var 的值每次都相同 为什么会改变?

C 指针内存 地址

评论

0赞 AKX 10/23/2023
在我看来,pptr 的值是 ptr 的地址,ptr 的值是 var 的地址,var 的地址是 var 的地址。其中两个预计是相同的。
0赞 Gerhardh 10/23/2023
在每个输出中,您将获得两次相同的地址。您希望哪些地址是相同的?所有地址?为什么?for 的输出如何与 for 相同?两个变量不共享相同的地址。// should be equal to address of ptr// should be equal to address of pptr
0赞 Bemin Dawoud 10/23/2023
是的,这正是我所理解的,我在评论中指出了这一点,但在这里 var 的地址第二次更改,我不明白为什么?
3赞 pmg 10/23/2023
en.wikipedia.org/wiki/Address_space_layout_randomization
2赞 Eric Postpischil 10/23/2023
@pmg:地址空间布局随机化不考虑四个字节的更改。它以虚拟内存页为单位工作。

答:

3赞 Eric Postpischil 10/23/2023 #1

在不打印的程序中,该对象不需要有地址,因此编译器能够通过不实际将程序存储在内存中来优化程序。该程序可以将 的值保存在处理器寄存器中和/或根据需要“动态”创建它。由于没有为其分配内存,因此会更改其他对象(如 )所在的位置。&pptrpptrvar

编译器可以使用复杂的算法为对象分配内存。然而,在这个有限的问题中,我们可以考虑一个简单化的观点。从本质上讲,编译器准备有关需要存储在堆栈上的对象的信息,然后在堆栈帧中为这些对象分配位置,结果是它为其分配位置的第一个对象将位于地址 0061FF14 16,下一个对象位于 0061FF1816,下一个对象位于 0061FF1C16。(堆栈帧中还有其他东西,这就是为什么我们在这种情况下看到的第一个对象从 0061FF14 16 开始,而不是从 0061FF1016 开始。main

在程序的第一个版本中,程序打印 、 和 的地址。因此,这些对象必须具有地址。无论出于何种原因,编译器都会按顺序处理它们,并分别为它们提供地址 0061FF14 16、0061FF1816 和 0061FF1C16varptrpptrpptrptrvar

在程序的第二个版本中,程序打印 和 的地址(后者通过分配 然后打印 )。它从不使用 的地址,因此不需要有实际地址;编译器能够在不放入内存的情况下使程序工作。因此,对于此程序,编译器为 和 分配内存,它们最终位于地址 0061FF14 16 和 0061FF1816因此,的地址与程序的第一个版本相差四个字节。varptr&ptrpptrpptrpptrpptrpptrvarptrptr