【问题标题】:Memory addresses of stack堆栈的内存地址
【发布时间】:2015-03-11 04:50:20
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    struct s1 {
        char *z;
        int i;
        struct s1 *p;
    };
    struct s1 *ptr;
    static struct s1 a[] = {
        {"Nagpur", 1, a + 1},
        {"Raipur", 2, a + 2},
        {"Kanpur", 3, a}
    };
    ptr = a;

    printf("%p\n", a[0]);
    printf("%p\n", a[1]);
    printf("%p\n", a[2]);
    printf("%p\n", ptr);
    printf("%p\n", a[2].p);
    printf("%p\n", a[1].p->p);
    printf("%p\n", a);

    return EXIT_SUCCESS;
}

只要我们有一个数组,假设我们称它为a[10],那么aa[0] 的地址是相等的。但在上述情况下,a 的地址和a[0] 的地址是不同的。我不知道为什么?

【问题讨论】:

  • 你不认为你的程序(和编译器)的输出会有帮助吗?
  • 我检查了输出,但我仍然无法弄清楚为什么它会给出这样的输出。你不认为如果我打印出ptr 它应该给出与a[0] 相同的结果吗?
  • 总是在打印数据指针之前添加cast to void *printf("%p\n", (void *)&amp;a[0]);。也可以使用-W -Wall -O2 编译以获得您的答案。
  • 好吧,我强烈建议不要使用任何优化,所以不要使用“-O2”,但是我真的很想看看这个程序的输出。该输出将对调试过程有很大帮​​助。
  • 带有 a[x] 参数的 printf() 调用不会打印地址,而是该偏移量的内容。这条线段:'那么a或a[0]的地址相等'是不正确的。但是,那么a的地址和a[0]的地址相等是真的。

标签: c pointers


【解决方案1】:

您传递给printf() 的是结构本身,而不是指向它的指针:

printf("%p\n", a[0]);

此代码的行为定义不明确。 (实际上,它通常最终会打印结构的第一个元素,但这可能不一致。)您可能想要的是:

printf("%p\n", &a[0]);
               ^

【讨论】:

  • a 怎么样。 &amp;aa 都给出相同的结果,但 *a 给出与 a[0] 相同的结果。请详细说明。
  • @GurucharanSharma 这是一个有据可查的数组衰减到指针的效果。请看:lysator.liu.se/c/c-faq/c-2.html
  • 感谢您的帮助。我真的很感激。
【解决方案2】:

如果你在编译时启用了警告(例如gcc -Wall -Werror),你会看到这一行:

printf("%p\n", a[0]);

无效:

ptr.c:20:5: error: format ‘%p’ expects argument of type ‘void *’, but
argument 2 has type ‘struct s1’ [-Werror=format=]
     printf("%p\n", a[0]);
     ^

您正在获取该结构的第 0 个元素,或者换句话说,取消引用 a,并将 struct s1 按值传递给 printf,它正在按照您所说的那样做,并且将其解释为指针。

如果你取而代之的是 address of 数组的第一个元素,你会发现它们确实在同一个地址:

printf("%p\n", &a[0]);

【讨论】:

    【解决方案3】:

    两者不同的原因是当您打印 a 时,它只是引用,而 a[0] 用于取消引用。试试 printf("%p\n",&a[0])。

    【讨论】:

      【解决方案4】:

      带有 a[x] 参数的 printf() 调用不会打印地址,而是打印该偏移量的内容。这条线段:'那么a或a[0]的地址相等'是不正确的。但是,那么a的地址和a[0]的地址相等是真的。 '%p' 格式转换器仅用于地址。所以代码需要使用地址,而不是内容。

      建议使用类似的东西:

      printf("%p\n", &a[0]); 
      printf("%p\n", &a[1]);
      printf("%p\n", &a[2]);
      printf("%p\n", ptr);
      printf("%p\n", a[2].p);
      printf("%p\n", a[1].p->p);
      printf("%p\n", a);
      

      【讨论】:

        【解决方案5】:

        您正在分配字符串的地址(例如“nagpur”)字符指针。这些字符串将出现在代码部分。因此“z”将具有这些字符串的地址,并且您正在尝试通过打印 a[0] 来打印这些地址。你应该打印 &a[0] 代替。 a[0] 与 *(a+0) 类似。所以如果你想打印它的地址,你应该使用 & 运算符。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-10-15
          • 2012-11-02
          • 2015-04-11
          • 1970-01-01
          • 2017-02-24
          • 2023-03-20
          • 2018-10-29
          相关资源
          最近更新 更多