我在 KN King 的书中第 269 页看到了这个声明
int a[ROWS][COLS], (*p)[COLS];
p = &a[0];
p
现在指向二维数组的第一行。我明白为什么a[0]
指向二维数组的第一行。但我不明白声明的语法p
。这是什么意思,我怎么记得?
周围的父母在*p
做什么?(*p)
这种语法在运算符优先级方面意味着什么?
我在 KN King 的书中第 269 页看到了这个声明
int a[ROWS][COLS], (*p)[COLS];
p = &a[0];
p
现在指向二维数组的第一行。我明白为什么a[0]
指向二维数组的第一行。但我不明白声明的语法p
。这是什么意思,我怎么记得?
周围的父母在*p
做什么?(*p)
这种语法在运算符优先级方面意味着什么?
> "But I do not understand the syntax for declaring p"
所以p
声明为:
int (*p)[COLS];
int
它是一个指向大小为s的数组的指针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 语言中,[]
优先于一元 *
,这意味着您需要()
in 才能p
成为指向int
s 数组的指针,而不是指向int
s 的指针数组。
后缀[]
和()
运算符都比一元运算符具有更高的优先级*
,因此它们首先绑定。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
是一个指向 ints 大数组的指针,COLS
声明不会分配那么多内存,但它确实允许进行一些边界检查。数组的内存是在声明中分配的:
a
=>int a[ROWS][COLS];
我明白为什么 a[0] 指向二维数组的第一行
这已经不准确了。在值上下文中,a[0]
并不真正指向“二维数组的第一行”。a[0]
实际上指向二维数组第一行的第一个元素。换句话说,在值上下文中a[0]
是一个指向a[0][0]
. a[0]
衰减到的类型int *
,您可能知道。并且sizeof *a[0]
等于sizeof(int)
。所以,它并没有真正指向整行。它指向一个单独的int
对象。
现在,如果你真的想指向二维数组的第一行,即指向整行,你需要&a[0]
. 这会给你一个 type 的指针int (*)[COLS]
。注意sizeof *&a[0]
等于sizeof (int[COLS])
,所以它确实是一个指向二维数组第一行的指针。这就是您在示例中看到的。
请注意,数字a[0]
和&a[0]
(作为值上下文中的指针)是相同的,因为它们指向线性内存中的同一点。但是,按类型&a[0]
指向整行,而a[0]
指向单个元素。