数组元素打印的地址是什么?

Sid*_*mal 1 c arrays pointers


更新:已报告此问题的可能重复.虽然提交给该问题的答案部分地解决了这个问题,但为了解释为什么我们不能使用双指针来表示二维数组,它没有指定如何访问存储在指针中的值的正确存储器地址; 这是这个问题的主题.这个问题中的明确答案可以很好地向未来混淆的人澄清为什么这是一个被误解的概念以及如何解决它的替代方法.这对于希望跟踪输出以更好地理解概念的未来读者可能是有用的(如果你仔细观察OP在该问题中的评论,你会发现跟踪不够清楚,他不能理解.这里提出的问题一部分提供了一个更好的跟踪示例,以便几乎任何人都可以轻松理解) (问题的其余部分是未经编辑的荣耀,以便未来的读者能够反思类似的错误,如果他们恰好成功的话.)


我正在做的事情:

  • 试图看看如何使用指针而不是2D数组
  • 在这种情况下,我将值插入2D数组(即a [] [])
  • 我试图用指针(即,ptr)访问该数组中的值
  • 我也试图跟踪从中获取这些值的内存地址
  • 试着知道我哪里出错了?(希望得到适当的解释,并在可能的情况下,提供参考链接并进一步学习)

我试过的:
下面是一个示例代码:

int main()
{
  int a[2][2]={{5,7},
               {0,1}};
  int** ptr=(int**)a;
  int i,j;
for(i=0;i<2;i++){
    for(j=0;j<2;j++){
        printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));
   }
  }
  getch();
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我试图在指针ptr的帮助下打印矩阵a [] []中存在的值.在这样做时,我正在跟踪打印实际发生的位置(在内存地址中).我似乎遇到了以下形式的灾难性输出:

5打印从==> 12ff7c
9打印从==> 12ff80
7打印来自==> 12ff80
11打印来自==> 12ff84

然后我修改了这一行:

printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));
Run Code Online (Sandbox Code Playgroud)

有了这个:

printf("%d printing from==>%d\n",&ptr[i][j],*((&ptr[i])+j));
Run Code Online (Sandbox Code Playgroud)

要知道这些地址中实际存在哪些值:

5打印从==> 5
9打印从==> 7
7打印从==> 7
11打印从==> 0

我对此的看法是:&ptr [i] [j]相当于(*(&ptr [i])+ j))和((&ptr [i])+ j))并没有真正告诉我的地址甚至那些数字因为&ptr [i]定义了一个地址,在这种情况下增加了j(但是因为j在每个外部循环迭代中被重置为0;这将导致相同的内存地址被指向两次) 我错了这个链思想?

你怎么能帮帮我?

  • 这是我的代码悲惨地失败,并基于我在这里阅读的关于C双指针和二维数组的文章.我是否从根本上误解了它?
  • 您可以通过在此处修改我的给定代码并在评论中发布您自己的perma-link来发布正确的cpp代码吗?(您可以通过单击该站点中编码区域下方的"GET URL"按钮来实现)
  • 我非常感谢基于C而不是C++的答案,其中typedef ans是可能的,我试图更好地学习指针

Ser*_*sta 5

2D数组和指针指针是不同的动物!

例如,2D阵列int arr[N][M]是具有以下关系的N*M个连续元素的阵列&arr[i][j] == &arr[0][0] + i * M + j.

指针指针是指向指针数组的指针,每个指针指向另一个数组.

所以,你可以做什么?

  • 使用显式索引将数组处理为一维数组

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int* ptr=a[0];  // a[0] decays to a pointer...
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[j + 2 *i],ptr + j + 2 * i);
        }
      }
      //getch();
      return(0);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 明确地创建一个指针数组

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int *b[] = { a[0], a[1] };  // array of pointers pointing to beginning or rows
      int** ptr=b;  // b decays to a pointer to pointer
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
        }
      }
      //getch();
      return(0);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 明确地使用指向确定大小的数组的指针:

    int main()
    {
      int a[2][2]={{5,7},
                   {0,1}};
      int (*ptr)[2] = a;  // a decays to a pointer arrays of size 2
      int i,j;
      for(i=0;i<2;i++){
        for(j=0;j<2;j++){
            printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
        }
      }
      //getch();
      return(0);
    }
    
    Run Code Online (Sandbox Code Playgroud)

另请注意,我在上面的代码中没有明确的强制转换,让编译器控制了无效级别是正确的.