【问题标题】:Dereferencing a pointer to 2d array取消引用指向二维数组的指针
【发布时间】:2021-03-27 18:36:14
【问题描述】:

我不明白为什么在取消引用指向数组的指针时,结果是数组第一个值的地址

int array[2][2] = {{0,1},{0,1}}; 
int (*p)[2];
p = array;

p = address of a[0][0], p+1 = address of a[1][0], 
*p = address of a[0][0], (*p)+1 = the address of a[0][1];

我知道 p 是指向 2 个整数数组的指针,而不是指向整数的指针。但是如果我们打印出 p 的值,它仍然是一个整数的地址。我想知道引擎盖下发生了什么? p 是指向指针数组的指针吗?所以我们必须解引用它两次才能得到它所指向的整数的值?

指向 int 的指针,

int* p;

是一个变量,存储在一个位置,其中包含另一个变量 (int) 的地址。

当我们取消引用它时,我们会得到那个变量的值。这个过程如何与指向数组的指针完全一致?

【问题讨论】:

  • 关于p = array; 不兼容的指针类型的赋值,您的警告说明了什么? int (*p)[2]; 是合适的。
  • 好的,我刚刚更正了
  • 在谈到数组及其与指针的关系时,您需要记住两件事。第一个是数组本身衰减为指向其第一个元素的指针。这意味着array&array[0] 完全相同。第二件事是对于任何数组或指针array和索引i,表达式array[i]完全等于*(array + i)
  • 二维数组是一个一维数组的数组p 指向array 中的第一个一维数组。所以p 指向array[0]p+1 指向array[1]。回想一下,在访问时,数组被转换为指向其第一个元素的指针。所以*p 将指向第一行的第一个元素(它与*(p+0) 相同,与p[0] 相同)
  • 而在处理数组和指针的时候,我真的建议你把它们画在纸上。对单个变量使用正方形,对数组使用矩形(划分以显示元素),对指针使用箭头。它通常有助于了解事物的概况。

标签: arrays c pointers


【解决方案1】:

数组的地址与其第一个元素的地址相同。

给定int array[2][2] = {{0,1},{0,1}};的定义,编译器在内存中安排一些位置来包含int值0、1、0和1。假设该位置的地址为1000,而int值0被存储1000-1003字节,1004-1007存储1,1008-1011存储0,1012-1015存储1。

元素array[0][0] 在内存中从哪里开始?在位置 1000。

数组array 在内存中的哪里开始?在位置 1000。

数组array[0] 在内存中的哪里开始?在位置 1000。

数组在内存中的第一个元素在内存中开始的相同位置开始。此外,array[0] 本身就是一个数组,从位置 1000 开始。

所以,p = array; 之后,p 指向位置 1000。而元素 array[0][0] 也从位置 1000 开始。因此,当您打印 p 时,与 printf("%p\n", (void *) p); 一样,您会得到与打印array[0][0] 的地址时的结果相同,与printf("%p\n", (void *) &array[0][0]); 一样。

数组会自动转换为其第一个元素的地址。

接下来,让我们考虑*pp 的类型是 int (*)[2],一个指向 2 个数组的指针 int。因此,*p 是一个包含 2 个int 的数组。

特别是,*p 是一个数组。假设我们尝试通过将其作为参数传递给printf 来打印它。会发生什么?

在 C 中,当在表达式中使用数组时,它会自动转换为其第一个元素的地址(除非数组是 sizeof 或一元 & 的操作数,或者是用于初始化一个数组)。因此,如果您使用*p 作为printf 的参数,它最初表示array[0],但该数组将转换为其第一个参数的地址。因此,将*p 作为参数传递实际上是通过&array[0][0](或等效于&(*p)[0])。

因此,printf("%p\n", (void *) *p); 将打印与printf("%p\n", (void *) &a[0][0]); 相同的地址。

【讨论】:

    【解决方案2】:
    1. 可以使用
      array[i] = *(array+i)[i] 的扩展)访问数组中的值。

    2. 同样,(*p)[i] = *(*(p+i))。因此,我们需要取消引用两次才能访问该值。

    3. 如果你想访问,array[0][0],你必须使用*(*(p+0)+0) = **p;, 同样,array[0][1] 可以使用*(*(p+0)+1) = *((*p)+1); 访问

    4. 注意,*p 指向第一行(存储地址array[0][0]),*(p+1) 指向第二行(存储地址array[1][0])。

    请检查以下代码:

    #include <stdio.h>
    int main()
    {
        int array[2][2] = {{1, 2}, {3, 4}};
        int(*p)[2];
        p = array;
    
    
        printf("The address of array[0][0] is %p \n",&array[0][0]);
        printf("The address of *p is %p \n",*p);
    
        printf("The address of array[1][0] is %p \n",&array[1][0]);
        printf("The address of *(p+1) is %p \n",*(p+1));
    
        printf("The value of array[0][0] is %d \n",array[0][0]);
        printf("The value of **p is %d \n",**p);
    
        printf("The value of array[0][1] is %d \n",array[0][1]);
        printf("The value of *((*p)+1) is %d \n",*((*p)+1));
    
    
        return 0;
    }
    

    输出是:

    The address of array[0][0] is 0x7fff6e8781a0 
    The address of *p is 0x7fff6e8781a0 
    The address of array[1][0] is 0x7fff6e8781a8 
    The address of *(p+1) is 0x7fff6e8781a8 
    The value of array[0][0] is 1 
    The value of **p is 1 
    The value of array[0][1] is 2 
    The value of *((*p)+1) is 2 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      • 2017-06-11
      • 2012-01-26
      相关资源
      最近更新 更多