首先,在你的问题中,你的意思是“typedef”,而不是“typecast”。
在C语言中,指向类型为T
的指针可以指向类型为T
的对象:
int *pi;
int i;
pi = &i;
上述内容很容易理解。现在,让我们稍微复杂一些。你似乎知道数组和指针之间的区别(即,你知道数组不是指针,但有时它们的行为类似)。因此,你应该能够理解:
int a[3];
int *pa = a;
但为了完整起见,关于这个赋值语句,变量名
a
等同于
&a[0]
,也就是数组
a
的第一个元素的指针。如果您不确定它是如何工作的以及为什么能够这样工作,有很多答案可以解释关于数组名“衰减”为指针的时机和原因,具体请查看:
我相信在 Stack Overflow 上还有许多类似的问题和回答,我只是列举了一些我从搜索中发现的。
回到主题:当我们有:
int foo[2][3];
foo
是类型为“array [2] of array [3] of int
”的数组。这意味着foo[0]
是一个包含3个int
的数组,而foo[1]
也是一个包含3个int
的数组。
现在假设我们想声明一个指针,并将其赋值给foo[0]
。也就是说,我们想执行以下操作:
/* declare p somehow */
p = foo[0];
上述代码与
int *pa = a;
行在形式上没有区别,因为
a
和
foo[0]
的类型相同。因此,我们需要使用
int *p;
来声明
p
。
现在,关于数组的主要事情是要记住,“规则”关于数组名称衰减到指向其第一个元素的指针仅适用一次。如果您有一个数组的数组,则在值上下文中,数组的名称不会衰减为类型“指向指针”,而是衰减为“指向数组”的指针。回到
foo
:
/* What should be the type of q? */
q = foo;
上面的
foo
名称是指向
foo
第一个元素的指针,也就是说,我们可以将上面的内容写成:
q = &foo[0]
foo[0]
的类型是"数组
[3]
,其中包含
int
类型的元素"。因此,我们需要
q
成为指向"数组
[3]
,其中包含
int
类型的元素"的指针:
int (*q)[3];
q
周围的括号是必需的,因为在C语言中
[]
的优先级比
*
高,所以
int *q[3]
声明
q
为指针数组,而我们需要一个指向数组的指针。从上面可以看出,
int *(q[3])
等同于
int *q[3]
,即一个包含3个指向
int
的指针的数组。
希望这能帮到您。您还应该阅读聪明人的C语言:数组和指针,这是一个非常好的教程。
关于阅读声明的一般方法:您需要“自内向外”阅读,从“变量”的名称(如果有)开始。尽可能向左移动,除非右侧紧接着一个[]
,并且始终遵守括号。 cdecl
应该能够在某种程度上帮助您:
$ cdecl
cdecl> declare p as pointer to array 3 of int
int (*p)[3]
cdecl> explain int (*p)[3]
declare p as pointer to array 3 of int
阅读
int (*a)[3];
a
(* )
[3]
int ;
为了
int *a[3];
a
[3]
*
int ;
为
char *(*(*a[])())()
a
[]
*
( )()
(* )
()
char *
(例子来自C语言常见问题第1.21问题。 实际上,如果您正在阅读这样一个复杂的声明,代码中一定有严重问题!)