$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
它也是另一种方式 .
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
406
我想我们可以使用简单的规则..
example int * (*ptr)()[];
start from ptr
“ ptr 是指向" go towards right ..its "的指针" now go left its a "(" come out go right "()" so "到一个不带参数的函数" go left "并将指针" go right "返回到整数数组" go left "”
250
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
int *a[4]; // Array of 4 pointers to int
int (*a)[4]; //a is a pointer to an integer array of size 4
int (*a[8])[5]; //a is an array of pointers to integer array of size 5
12 回答
根据经验,右一元运算符(如
[]
,()
等)优先于左运算符 . 所以,int *(*ptr)()[];
将是一个指向一个函数的指针,该函数返回一个指向int的指针数组(当你离开括号时,尽快得到正确的运算符)在指向整数的指针中,如果指针递增,则它将转到下一个整数 .
在指针数组中,如果指针递增,它将跳转到下一个数组
按照K&R的建议使用cdecl程序 .
它也是另一种方式 .
我想我们可以使用简单的规则..
“
ptr
是指向" go towards right ..its "的指针" now go left its a "(" come out go right "()" so "到一个不带参数的函数" go left "并将指针" go right "返回到整数数组" go left "”第三个与第一个相同 .
一般规则是operator precedence . 随着函数指针的出现,它可以变得更加复杂 .
我不知道它是否有正式名称,但我称之为Right-Left Thingy(TM) .
从变量开始,然后向右,向左,向右......等等 .
arr1是一个包含8个整数指针的数组 .
arr2是指向8个整数数组的指针(括号内的左右) .
arr3是一个包含8个整数指针的数组 .
这应该可以帮助您完成复杂的声明 .
这是我如何解释它:
所以,这里我们将在'*'之前应用'[]',使语句等效于:
这可以读作,((某物的第i个索引处的值))是一个整数 . 所以,(某事物的第i个索引处的值)是一个(整数指针),这使得某个东西成为整数指针的数组 .
在第二个,
要理解这个陈述,你必须熟悉这个事实:
所以,用(* something)替换somethingElse,我们得到*(某事我),这是一个声明的整数 . 所以,( something)给了我们一个数组,它使得某些东西等同于(指向数组的指针) .
这是一个有趣的网站,解释了如何在C中读取复杂类型:http://www.unixwiz.net/techtips/reading-cdecl.html
最后两个答案也可以从C中的黄金法则中扣除:
int (*arr2)[8];
如果你取消引用arr2会发生什么?你得到一个8个整数的数组 .
int *(arr3[8]);
如果你从arr3中获取一个元素会怎么样?你得到一个指向整数的指针 .
这在处理指向函数的指针时也很有用 . 以sigjuice为例:
float *(*x)(void )
取消引用x后会发生什么?你得到一个你可以不带参数调用的函数 . 你打电话后会发生什么?它将返回指向float的指针 .
但是,运算符优先级总是很棘手 . 但是,使用括号实际上也可能会造成混淆,因为声明跟随使用 . 至少对我而言,直观地说,arr2看起来像一个由8个指针组成的数组,但它实际上是另一种方式 . 只需要一些习惯 . 足够的理由总是在这些声明中添加注释,如果你问我:)
edit: example
顺便说一句,我偶然发现了以下情况:一个具有静态矩阵的函数,它使用指针算法来查看行指针是否超出范围 . 例:
输出:
请注意,border的值永远不会改变,因此编译器可以对其进行优化 . 这与您最初可能要使用的内容不同:
const int (*border)[3]
:将border声明为指向3个整数数组的指针,只要该变量存在,该数组就不会更改值 . 但是,该指针可以在任何时候指向任何其他这样的数组 . 我们想要参数的那种行为(因为这个函数不会改变任何整数) . 声明如下使用 .(p.s . :随意改进这个样本!)
我想第二个声明让许多人感到困惑 . 这是一种理解它的简单方法 .
让我们有一个整数数组,即
int B[8]
.让我们也有一个指向B的变量A.现在,A的值是B,即
(*A) == B
. 因此A指向整数数组 . 在你的问题中,arr类似于A.类似地,在
int* (*C) [8]
中,C是指向整数指针数组的指针 .