要使用typedef
声明一个函数指针,它将类似于:
typedef void (*FOO)(int i)
但通常typedef
的语法如下:
typedef int BOOL
那么为什么第一个不是:
typedef void (*)(int) FOO
要返回一个函数指针(不带typedef
),语法如下:
void (*foo(char c))(int)
这意味着foo
接受一个char并返回一个指向函数的指针,该函数接受一个int并且不返回任何内容。语法太奇怪了!看起来foo
接受一个int并且什么都不返回。括号似乎没有在正确的位置。如果要返回一个函数指针,为什么它不是这样的:
(void (*)(int)) foo(char c)
这非常简单。我真的很难理解这里的语法,更不用说使用它了。有人可以解释一下这里发生了什么吗?
答案 0 :(得分:4)
整数只是:
int x;
上述名称由:
给出typedef int x_type;
指向int
的指针是:
int *p;
它的类型是:
typedef int *p_type;
一个名为foo
的函数采用double``and returning an
int`:
int foo(double);
定义foo
的类型为:
typedef int foo_type(double);
现在指向上面的指针应该是*
,但是()
(函数调用)绑定比*
(解除引用)更紧,所以parentesis:
typedef int (*ptr_to_foo_type)(double);
这可能写得更好:
typedef foo_type *ptr_to_foo_type;
正如一些人建议的那样,为了清晰起见。
这个想法是类型描述看起来(有点)像它的用途。给出前缀/后缀运算符的严重错误的想法,很多人都同意。但现在改变已经太晚了。
答案 1 :(得分:1)
声明语法基于表达式的类型,而不是对象。另一种说法是"声明模仿使用"。
让我们从简单的指针表达式开始;称之为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
运算符进行explcitly分组。
表达式的类型 (*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;
的行为。
答案 2 :(得分:0)
1)typedef的语法是声明该类型的变量并将typedef
放在它前面。
2)声明的语法回应了实际获取该类型值的语法。请参阅我最近关于寻址运算符(包括函数调用)优先级的其他答案,例如(*twod)[3] vs *(twod)[3] C Pointers ...我不想再重复一遍。