声明语法基于表达式类型,而不是对象类型。另一种说法是,“声明模仿使用”。
让我们从一个简单的指针表达式开始;称之为iptr。 iptr指向一个整数值。 如果我们想要访问该值,我们需要使用一元*运算符对iptr进行解引用,像这样:
x = *iptr;
表达式 *iptr
的类型为 int
,因此声明 iptr
的语法如下:
int *iptr;
如果您想为一个 int
指针创建一个 typedef,您需要添加 typedef
来实现。
typedef int *iptr;
iptr
现在作为类型“指向int
的指针”的同义词,所以您可以编写:
iptr ip;
该语句将 ip
声明为指向 int
的指针(通常情况下,您真的不想在 typedef 中隐藏指针)。
现在假设您有一个指向接受两个 int
参数并返回 int
值的函数的指针,称其为 fp
。要调用该函数,您需要解引用指针并将必要的参数传递给结果函数,如下所示:
x = (*fp)(arg1, arg2); // C allows you to omit the * in the call, so you could
// also write it as simply x = fp(arg1, arg2), but we're
// leaving it in so the following explanation makes sense
函数调用
()
运算符的优先级高于一元
*
;
*fp()
将被解释为
*(fp())
,这不是我们想要的。为了在调用它指向的函数之前取消引用
fp
,我们必须显式地将
*
运算符与
fp
分组。
表达式
(*fp)(arg1, arg2)
的类型为
int
,因此
fp
的声明变为:
int (*fp)(int arg1, int arg2);
现在让我们看一下你的第二个例子:foo
是一个函数,它接受一个 char
参数,并返回一个指向一个接受 int
参数并返回 void
的函数的指针。你可以像这样调用它:
(*foo(c))(x);
再次强调,表达式 (*foo(c))(x)
的类型为 void
,因此声明应该是
void (*foo(char c))(int x);
为了语法上的原因,
typedef
被视为存储类说明符,就像
extern
或
static
一样,尽管它有非常不同的含义。它不会改变声明的结构;它只是改变了编译器如何解释该声明的方式。将
typedef
添加到上面的内容中,如下所示:
typedef void (*foo(char c))(int x);
现在创建了同义词
foo
,用于表示返回指向返回
void
的函数指针的函数类型。这与更简单的类型定义没有区别,例如:
typedef int *iptr;
表现良好。
foo
,而是foo(...)
。 - deviantfan