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

4
我在KN King的书第269页遇到了这个声明。
int a[ROWS][COLS], (*p)[COLS];

p = &a[0];

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

围绕*p的括号是什么意思?(* p)在运算符优先级方面意味着什么?


简单来说,它是一个指向类型为int的cols个元素的数组的指针。将其提取出来并像* p(一个指针)一样进行分析,然后是一个数组声明(* p)[],然后是每个元素类型int。数组大小为cols。现在,由于编辑parn围绕p的括号使其被声明为指向某物的指针,而不是int指针的数组。 - Koushik Shetty
括号是因为否则 [] 会在 * 之前绑定。int *p[COLS] 是指针数组,int (*p)[COLS] 是指向数组的指针。 - Carl Norum
4个回答

18

> "但我不理解声明p的语法"

因此,p 声明为:

int (*p)[COLS];

这是一个指向大小为COLSint数组的指针。 >“这是什么意思,我该如何记住它?” 您可以使用螺旋法则并从()中开始工作来判断。
    ( 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

当然,你也可以通过作弊来获得答案

enter image description here

> "这个语法在运算符优先级方面是什么意思?"

C语言中,[]的优先级高于一元运算符*, 这意味着你需要使用()来使p成为指向int数组的指针,而不是指向int指针的数组。


2

后缀运算符[]()的优先级比一元运算符*高,因此它们首先绑定。也就是说,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

2
我理解为什么a [0]指向2D数组的第一行。
这已经不准确了。在值上下文中,a [0]实际上并没有真正指向“2D数组的第一行”。实际上,a [0]指向2D数组第一行的第一个元素。换句话说,在值上下文中,a [0]是指向a [0] [0]的指针。正如您可能知道的那样,a [0]的类型衰减为int *。而且sizeof * a [0]等于sizeof(int)。因此,它并没有真正指向整个行。它指向孤立的int对象。
现在,如果你真的想指向一个二维数组的第一行,即指向整个行,你需要使用&a[0]。这将给你一个类型为int (*)[COLS]的指针。请注意,sizeof *&a[0]等于sizeof (int[COLS]),因此它确实是一个指向二维数组第一行的指针。这就是你在例子中看到的。
请注意,数值上a[0]&a[0](作为指针在值上下文中)是相同的,因为它们指向线性内存中的同一位置。然而,从类型上讲,&a[0]指向整个行,而a[0]指向单个元素。

1

忽略逗号并重新编写为:

int a[ROWS][COLS];
int (*p)[COLS];

p = &a[0];

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


这是我第一次看到这样声明指针的方式。所以,如果将 p 增加 1,它现在将指向第二行的第一个元素? - user1222021
@CarlNorum,你能向我描述一下语法或者给我提供一个参考吗? - Ankur Agarwal
@CarlNorum 谢谢!今天学到了新东西!=) - user1222021
1
这是一个普通的C指向数组的指针。建议查看一些初学者书籍或教程,也许你会发现cdecl工具很有帮助。 - Carl Norum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接