用于指向一行二维数组的C指针声明

我在第269页的KN King的书中看到了这个宣言

int a[ROWS][COLS], (*p)[COLS]; p = &a[0]; 

p现在指向第二行的二维数组。 我理解为什么a[0]指向第一行的二维数组。 但我不明白声明p的语法。 这是什么意思,我怎么记得它?

*p做什么的parens? (*p)这种语法在运算符优先级方面意味着什么?

> "But I do not understand the syntax for declaring p"

所以p被声明为:

 int (*p)[COLS]; 

它是一个指向int数组的指针,它的大小是COLS

> "What does that mean and how do I remember it?"

以下是如何判断, 使用螺旋规则并从() s开始:

  ( p) p (*p) p is a pointer (*p)[ ] p is a pointer to an array int (*p)[ ] p is a pointer to an array of ints int (*p)[COLS] p is a pointer to an array of ints of size COLS 

当然,你总是可以作弊来得到答案 :

在此处输入图像描述

> "what does this syntax mean in terms of operator precedence?"

在C语言中, []优先于一元* ,这意味着您需要()以使p成为指向int数组的指针,而不是指向int的指针数组。

postfix []()运算符的优先级都高于一元*运算符,因此它们首先绑定。 IOW, T *p[N]被解释为T *(p[N]) ; p是指向T的指针数组。 为了声明一个指向数组 (或指向函数的指针)的指针,你必须使用括号来强制*运算符在[]之前绑定:

 T *p[N]; // p is an array of pointer to T T (*p)[N]; // p is a pointer to an array of T T *f(); // f is a function returning pointer to T T (*f)(); // f is a pointer to a function returning T 

忽略逗号并重写为:

 int a[ROWS][COLS]; int (*p)[COLS]; p = &a[0]; 

p是一个指向int的数组的指针COLS很大声明没有分配那么多的内存,但它确实允许一些边界检查。 数组的内存在以下声明中分配:
a => int a[ROWS][COLS];

我理解为什么[0]指向第一行的二维数组

这已经不准确了。 在值上下文中, a[0]并不真正指向“2D数组的第一行”。 a[0]实际上指向第一行2D数组的第一个元素 。 换句话说,在值上下文中a[0]是指向a[0][0]的指针。 正如您可能知道的那样, a[0]的类型衰减为int *sizeof *a[0]等于sizeof(int) 。 所以,它并没有真正指向整行。 它指向一个孤立的int对象。

现在,如果你真的想指向2D数组的第一行,即指向行,你需要&a[0] 。 那会给你一个int (*)[COLS]类型的指针。 请注意, sizeof *&a[0]等于sizeof (int[COLS]) ,因此它确实是指向2D数组第一行的指针。 这是您在示例中看到的内容。

注意,数字a[0]&a[0] (作为值上下文中的指针)是相同的,因为它们指向线性存储器中的相同点。 但是,类型&a[0]指向整行,而a[0]指向单个元素。