在 printf 中给出不同结果的指针

Pointers giving different results in printf

我正在学习一些 C,我正在测试简单的指针事物,以便我能更多地理解它们。 我想我没有得到正确的东西。 给出下面的简单代码:

#include <stdio.h>

void main() {
    long n = 1;
    long *y = &n;
    n = 2;
    printf("n: %d\n",&n);
    printf("y: %d\n",y);
}

结果是:

n: 6422296
y: 6422296

我猜是内存中的哪个位置。

如果我将打印行更改为:

printf("n: %d\n",&n);
printf("y: %d\n",&y);

结果是:

n: 6422300
y: 6422296

我猜 n 在内存中存储在 y 之后的 4 个字节,但不明白为什么。我没有更改输出中的 n,我将 & 保留在其中,但是当将 & 添加到 y 时,输出值会发生变化。

如果我这样离开:

printf("n: %d\n",n);
printf("y: %d\n",&y);

输出为:

n: 2
y: 6422296

这个结果是我所期待的。

为什么会出现这种行为? 我缺少一些东西。

不要无礼。我阅读了有关指针的教程和解释,但没有人为我解释这些。

n 是一个 long,y 是一个指向 long 的指针。都占用自己的内存

我稍微修改了你的代码:

#include <stdio.h>

void main() {
    long n = 1;
    long *y = &n;
    n = 2;
    printf("&n: %p\n",&n); //Please change format specifier to %p for pointer
    printf("y: %p\n",y);
}

在第一个 printf() 调用中打印 n 的地址,在第二个 printf() 调用中打印存储在 y 中的值。因为你用 n 的地址初始化 y,所以它们必须相同。

在你的下一组 printf() 中(再次稍作修改):

printf("n: %ld\n",n); //Please change format specifier to %ld for long int
printf("&y: %p\n",&y); //This one is still a pointer though (long**)

您正在打印 n 的值和 y 的地址。

第一个 printf() 必须打印 2 因为它是存储在 n 中的最新值。第二个printf()是要打印y的地址,也就是存放n地址的内存地址。 &y 是指向 long 的指针。

printf("&y: %p\n",&y);

永远无法打印n的地址,因为yn存储在不同的内存位置

y给你值,就是n的地址。

&y 给你 y 的地址,不管 y 是什么类型。

  • & 是地址运算符。它给你变量的地址。
  • * 在表达式中使用时,是取消引用运算符。它为您提供指针指向的值。在您的示例中 *y 将为您提供 n.
  • 的值
  • * 在声明中使用时(例如您的 long *y)指定变量将包含 address/pointer.

要学习和理解 C,阅读著名的 C FAQ.

的相应部分会有所帮助

我认为您的问题归结为“为什么当我添加 y 地址的打印时 n 的地址会发生变化”。答案归结为编译器和优化器如何工作以及它们如何为事物分配存储的细节。

当你像这样声明一个函数的局部变量时,编译器在如何处理它方面有很大的自由度。它可以在它为函数创建的堆栈帧中分配 space ,或者它可以将变量保存在寄存器中,或者它可以两者都做,或者它甚至可以做其他事情。唯一的要求是它最终生成的代码与程序的执行语义相匹配。

在像这样的局部变量的情况下,如果它们的地址从未被获取(如 y 的情况),那么一个好的编译器通常会尝试将变量保存在寄存器中并且从不分配对它的记忆。因此,在第一个程序中,堆栈帧中的一个变量(n)只需要 space(n 已占用其地址,因此必须驻留在内存中才能获得地址)。

在第二个程序中,yn的地址都被占用了,所以它们都必须在内存中。碰巧编译器决定将 y 放在较低的地址,n 放在较大的地址,但并不能保证这一点。也没有要求它们在任何意义上都“相邻”。