这是考试问题之一,目标是确定该课程的内容。我对int (*f[])(int*) = {f1, f2, f2, f1 };
是什么感到困惑。我教过它可能是一个数组,其元素是括号中函数的结果,那些结果是指向int的地址。
你能解释一下吗?
同样,函数f[i++]
进入的参数是什么参数
for (i=0; i<2; a += fx(f[i++], a));
问题:
int f2(int *p) { return *p-- + 2; }
int f1(int *q) { return ++*q; }
int fx(int (*pf)(int*), int q) {
int t = q;
while ((t = pf(&q)) % 2) q+=2;
return t;
}
#include <stdio.h>
void main() {
int a = 4, b = 3, *p = &b, i;
int (*f[])(int*) = {f1, f2, f2, f1 };
for (i=0; i<2; a += **fx(f[i++]**, a));
printf("%d", a + *p);
}
答案 0 :(得分:11)
int (*f[])(int*)
^ f is
int (*f[])(int*)
^^^ f is an array
int (*f[])(int*)
^^^^^^ f is an array of pointers
int (*f[])(int*)
^^^^^^^....^ f is an array of pointers to functions
int (*f[])(int*)
^^^^^^^^^^^^ f is an array of pointers to functions
that accept a pointer to int
int (*f[])(int*)
^^^^^^^^^^^^^^^^ f is an array of pointers to functions
that accept a pointer to int and return a int value
答案 1 :(得分:4)
它将f
声明为函数指针数组,返回int
并将int *
作为参数。
有一个用于理解复杂声明的优先规则,这在Expert C Programming: Deep C Secrets一书中讨论过:
理解C声明的优先规则
一个。通过从名称开始然后按优先顺序阅读来读取声明。
B中。优先级从高到低依次为:
B.1。括号将声明的部分组合在一起
B.2。后缀运算符:
括号()
表示功能,和
方括号[]
表示数组。B.3。前缀运算符:
星号表示“指向”。
- ℃。如果
const
和/或volatile
关键字位于类型说明符旁边(例如int
,long
,etc
。),则它适用于类型说明符。否则,const
和/或volatile
关键字将应用于其左侧的指针星号。
因此,它就像:
f -- f (A)
f[] -- is an array (B.1)
*f[] -- of pointers to (B.3)
(*f[])( ) -- function (B.2)
(*f[])( int * ) -- that expects a pointer to an int as an argument
int (*f[])( int* ) -- and return an int
我建议在某些情况下避免使用螺旋规则fails,例如int* a[10][15];
。
答案 2 :(得分:2)
让我们在令人敬畏的C gibberish to English website:
的帮助下将其分开int (*f[])(int*)
将f声明为指向函数的指针数组(指向int的指针),返回int
f
是一个函数指针数组。
因此,使用{}
数组初始值设定项将函数存储在其中非常清楚。
答案 3 :(得分:1)
与通常的教学方法不同,我建议你从外部开始。识别声明的一般结构并进行细化:替换粗粒度的&#34; blob&#34;你看到更详细的。换句话说,将语法从语法树的根遍历到叶子,而不是试图挑选出正确的叶子并自下而上。
声明的一般结构(具有单个声明者)是:
TYPE WHATEVER;
WHATEVER
正在宣布,与TYPE
相关。
现在请注意TYPE
为int
,因此WHATEVER
的类型为int
。 WHATEVER
具有一般形状(W1)(W2)
:括号中有两个句法单位,无论是1还是2:
int (W1)(W2);
这里,W1
是被声明的内容,它是一个返回int
的函数,它接受W2
参数列表。后者实际上表示int *
:
int (W1)(int *);
因此,W1
是一个返回int
的函数,需要int *
。但W1
实际上是*W3
,这使得W3
成为指向W1
类型的指针。
int (*W3)(int *);
W3
是指向返回int
的函数的指针,该函数需要int *
。
W3
实际上是f[]
,因此f
是一个未指定大小W3
类型的数组:
int (*f[])(int *);
f
是一个未指定大小的指向函数的数组,用于返回int
int *
的函数。
提示:我们如何知道W1
实际上W3[]
W3
当时*f
是不是[...]
?这是因为类型构造运算符[...]
在语法上类似于后缀数组索引运算符*
,构造*
的类型类似于解除引用的一元运算符*X[]
。一元运算符比后缀运算符具有更低的先行。当我们看到*(X[])
时,我们知道它意味着(*X)[]
而不是*X
。符号 declaration
| |
+------------+ +----------------+
| |
specifier-qualifier list -- TYPE declarator -- WHATEVER
| | |
int +-----+ |
| |
function -- W1 params -- W2
| |
pointer -- W3 (int *)
|
array -- f
不会在该短语中形成句法单位。如果我们想要第二个含义,我们必须使用括号。
语法树是:
W3
像C
这样的有用符号只是我们从根到叶子遍历时节点的标签。在f
声明中声明的名称位于树的底部,与其他语言不同。随着更深入进入树,我们实际上正在出现 out 类型,所以当我们到达底部时,我们知道最重要的事情:{{1}正在被声明,总的来说它是一个数组。
答案 4 :(得分:0)
在the clockwise/spiral rule之后,我们将看到f
是一个指向函数的指针数组,其中数组中的每个函数都采用int*
参数并返回int
。
初始化只是用一些函数指针初始化这个数组。
知道f
是什么应该有助于解决另一个问题。
答案 5 :(得分:0)
此
int (*f[])(int*) = {f1, f2, f2, f1 };
是int(int *)类型的函数指针数组的声明,其函数具有返回类型int
和一个类型为int *
的参数。
由于f
是一个数组,因此f[i++]
是数组的元素,其中包含值f1,f2之一等等。
此功能
int fx(int (*pf)(int*), int q);
有两个参数:指向类型为int(int *)的函数的指针和类型为int的对象。
所以这个表达
fx(f[i++], a)
是一个函数调用,它作为参数访问函数指针f1,f2之类,依此类推,对象a
答案 6 :(得分:0)
它实质上定义了一个函数指针数组。以下内容:
int (*f[])(int*) = {f1, f2, f2, f1};
将定义与数组初始值设定项相结合。这就是为什么你可以省略数组的大小,因为它是从初始化器推导出来的。每个元素的类型是:
int (*)(int*)
是函数的函数指针,它接受一个int *
类型的参数并返回int
。
for
循环的主体由空语句组成。为了更清晰,您可以重写它:
for (i = 0 ; i < 2; a += fx(f[i++], a))
;
i = 0
和i = 1
有两次迭代。每次a
由函数调用的结果递增:
fx(f[i++], a)
第一个参数是函数的地址,存储在f
数组中。它分别是f[0]
和f[1]
(即f1
和f2
)。您可以使用等效形式:
fx(&f[i++], a)
但没有真正的区别(这只是偏好问题)。
如果它看起来太奇怪或太复杂,那么您可以将for
循环重写为:
for (i = 0 ; i < 2; a += fx(f[i], a), i++)
;
以及:
for (i = 0 ; i < 2; i++)
a += fx(f[i], a);