1

我在使用以下代码时遇到问题:

int a[] = {1, 2, 3, 4};
  
fprintf(stdout,
        "a      : %lu\n"
        "*a     : %d\n"
        "&a     : %ld\n"
        "**(&a) : %d\n",
        (unsigned long int)a,
        *a,
        (unsigned long int)&a,
        **(&a)
);

输出:

a      : 140726063647232
*a     : 1
&a     : 140726063647232
**(&a) : 1

我知道这&a是一个指向一维数组的指针。而&a的类型是int (*)[4]。我很困惑是怎么来的**(&a): 1

4

3 回答 3

1

另一种看待它的方法是通过每个地址取消引用操作之后的结果类型。数组访问的基本规则是数组指针转换。C11 标准 - 6.3.2.1 其他操作数 -适用于访问任何数组的左值、数组和函数指示符 (p3)(受列出的 4 个例外 [C18 标准中的 3 个 -_Alignof不再列出])。

关键是要了解数组在访问时会转换为指向第一个元素的指针(受限于有限的例外 - 此处不相关)。如果取数组的地址,地址与第一个元素的地址相同,但指针的类型完全不同

     a   - pointer to int
    &a   - pointer-to-array int[4], proper type: int (*)[4]

当你取消引用时a,你会得到第一个元素:

    *a   - int

为什么?*a是偏移量为 的完全解引用操作的缩写0,例如 *(a + 0),它相当于a[0]in index notation.

当您取消引用指向数组的指针 int[4]时,您将返回数组:

 *(&a)   - int[4] -> converted to pointer to first element.

然后,通过6.3.2.1(p3)的操作将其转换为指向第一个元素的指针。再次取消引用,您将获得第一个元素:

**(&a)   - int

现在值得学习,因为它会在以后为您节省很多困惑。

于 2020-06-30T05:24:49.450 回答
1

&a是指向数组的指针。*p获取指针指向的内容,因此*&a获取数组,a.

被视为指针的数组退化为指向其第一个元素的指针*a1.

既然*&aa**&a是 一样 的*a, 那 就是1

于 2020-06-30T05:00:30.953 回答
1
  1. 如果你想打印一个你应该为or函数address使用%p转换说明符。printffprintf
  2. 另一方面,integer data type使用与上述相同的功能进行打印时,您应该使用%d转换说明符。那么您可以省略所有向上转换为unsigned long int数据类型。
  3. c arrays在您的情况下衰减为相同数据类型的指针(并非在所有情况下数组都可以decays指向指针)。在您的打印中,您已经使用了这个事实,例如在取消引用数组时*a。c 中的这一事实使我们能够扭曲以下语句: int* a_ptr = a; AND int* ptr = &a[0];。现在a_ptrptr是平等的!指向内存中的相同地址。
  4. 打印a就像打印a_ptr值和打印值一样ptr。以打印结束&a[0]
  5. 打印*a就像打印 *a_ptr 和打印一样*ptr,从那时ptr = &a[0];起,*ptr == *&a[0]==a[0]所以简单来说它a[0]就是1
  6. 印刷&a。现在是什么&a?它是一个指向整数数组的指针!更准确地说,它是一个指向 4 个整数数组的指针,int (*)[4]因此在打印 a 的地址时就像打印其取消引用*(int (*)[4])是数组 simple 的地址一样a。请注意,数据类型完全不同!a&a
  7. 打印**(&a)是一样的*(*(int (*)[4]))是一样的 是一样的 是的 是的*(a)是的是的是的*(a+0)*ptra[0]1

将代码段修复为:

int a[] = {1, 2, 3, 4};

fprintf(stdout,    /*you can use printf instead of fprintf(srdout,)*/
    "a      : %p\n"
    "*a     : %d\n"
    "&a     : %p\n"
    "**(&a) : %d\n",
       a,
      *a,
      &a,
   **(&a)
);
于 2020-06-30T06:13:47.463 回答