C 指向 array/array 的指针消歧(扩展)

C pointer to array/array of pointers disambiguation (extended)

There is a post where different pointer notations are explained:

int* arr1[8]; // An array of int pointers.
int (*arr2)[8]; // A pointer to an array of integers
int *(arr3[8]); // The same as the first one

但是也可以这样定义:

int (*arr4[8])

这里除了数据类型名称之外的所有内容都用括号括起来。它与前三个选项有何不同?

我也试过像 (int *arr4[8]) 那样把它括起来,但似乎这在 C 中是无效的。

我也很好奇这样的构造:

int (*arr5[8])[8]

不确定,但我认为这类似于指向整数数组的指针数组。 如果我需要指定一个指向这种构造的指针,我认为这是这样的:

int (*(*arr5[8]))[8]

如果我把最外面的括号放在一边,我猜这类似于 指向整数指针数组的指针数组,是吗?

int *(*arr5[8])[8]

都对吗?提前致谢!

您可以将声明符括在括号中。

这个声明

int (*arr4[8]);

声明了一个类型为 int * 的包含 8 个元素的数组。和写

一样
int * arr4[8];

至于这个声明

int (*(*arr5[8]))[8];

为了清楚起见,请考虑以下演示程序。

#include <stdio.h>

int main(void) 
{
    int a1[8] = { [0] = 10 };
    int a2[8] = { [0] = 20 };
    
    int ( *p1 )[8] = &a1;
    int ( *p2 )[8] = &a2;
    
    int (*(*arr5[8]))[8] =
    {
        &p1, &p2
    };
    
    printf( "%d\n", ( **arr5[0] )[0] );
    printf( "%d\n", ( **arr5[1] )[0] );
    
    return 0;
}

程序输出为

10
20

就是这个声明

int (*(*arr5[8]))[8]

声明了一个指针数组,这些指针指向类型为 int[8] 的数组。

int (*arr4[8])

Here everything except the datatype name is enclosed with parentheses. How is it different from the firts three options?

括号唯一重要的时候是当它们改变运算符的默认优先级时。后缀 []() 在声明符和表达式中都比一元 * 具有更高的优先级,因此 *arr4[8] 被解析为 *(arr4[8])(*arr4[8]) 不影响 *[] 的优先级,因此它与编写 *(arr4[8])*arr4[8] 相同。但是,对于 (*arr3)[8],他们 do 改变了优先级,明确地将 * 运算符与 arr.

分组

I tried to enclose it like (int *arr4[8]) as well, but seems like this is not valid in C.

这不是 - 语法不允许。

int (*arr5[8])[8]

Not sure, but I presume this is something like an array of pointers to an array of integers.

准确地说,arr5是指向int的8元素数组的指针的8元素数组。从图形上看,它看起来像这样:

      +---+                     +---+---+---+---+---+---+---+---+     
arr5: |   | arr5[0] ----------> |   |   |   |   |   |   |   |   |
      +---+                     +---+---+---+---+---+---+---+---+
      |   | arr5[1] --------+
      +---+                 |   +---+---+---+---+---+---+---+---+
      |   | arr5[2] ------+ +-> |   |   |   |   |   |   |   |   |
      +---+               |     +---+---+---+---+---+---+---+---+
       ...                |     
                          |     +---+---+---+---+---+---+---+---+
                          +---> |   |   |   |   |   |   |   |   |
                                +---+---+---+---+---+---+---+---+

你会将每个元素索引为 (*arr5[i])[j] - 你不想索引到每个 arr5[i],你想索引到每个 arr5[i] 点至。声明者预先告诉你这一点——你不必自己去弄明白。声明符的结构反映了表达式的结构。

请注意,此声明不会创建 int 的 8 元素数组 - 它 创建一个 8 元素指针数组。您可能需要为每个要指向的 arr5[i] 动态分配内存,例如:

for ( size_t i = 0; i < 8; i++ )
  arr5[i] = malloc( sizeof *arr5[i] ); // sizeof *arr5[i] == sizeof (int [8])

或者已经声明了一堆数组:

int foo[8];
int bar[8];
int bletch[8];
...
int (*arr5[8])[8] = { &foo, &bar, &bletch, ... };