如何使用typedef定义函数类型?

3

我想知道是否可以使用typedef来定义函数类型,我尝试了以下语法:

typedef int (*) (void *, void *) order;

但是它不起作用。 错误信息:在 ')' 标记之前期望标识符或 '('

可能是理解C语言中函数指针的typedef的重复问题。 - mkrieger1
4个回答

14

如果它是一个变量声明,别名应该放置在变量名应该放的位置。

这里:

typedef int (*order) (void *, void *);
//            ^~~~~

或者,如果你想要一个函数类型而不是指向函数的指针:

typedef int order(void *, void *);

声明函数类型的原因是什么? - ThunderPhoenix
实际上,我需要一个函数指针来在调用qsort函数时进行转换。 - ThunderPhoenix
@ThunderPheonix 我以为你在询问函数和指向函数的指针之间的区别。无论如何,将一个函数转换为具有不同参数类型或返回类型的函数指针是一个坏主意,并且调用产生的指针会导致未定义的行为(见C11 6.3.2.3/8)。 - HolyBlackCat
我只是想避免qsort的警告信息! - ThunderPhoenix
@ThunderPheonix 确保您传递的函数看起来像 int name(const void *, const void *)。那么您就不需要进行转换了。 - HolyBlackCat
显示剩余2条评论

6
这是一个 typedef。
typedef int (*order )(void *, void *);

定义了一个指向类型为 int( void *, void * ) 的函数指针的别名。

这个 typedef

typedef int order(void *, void *);

定义了一个类型为int( void *, void * )函数类型的别名。

如果要使用一个typedef来同时定义指针和函数类型的别名,可以这样写:

typedef int ( *porder )( void *, void * ), order(void *, void *);

甚至可以使用以下的方式。
int typedef ( *porder )( void *, void * ), order(void *, void *);

请注意,您可以将typedef名称用作函数参数的类型说明符。例如,这两个声明:
void h( porder arg );
void h( order arg );

声明同一个函数,因为编译器会自动调整函数类型的参数类型为指向函数类型的指针。

但是,你可能无法将这些typedef用于函数返回类型的可互换性,因为函数不能返回函数,但它们可以返回指向函数的指针。所以这个声明:

porder h( void );

这段代码将会编译通过。但是这个声明

order h( void );

无法编译。

如果没有 typedef,返回指向其他函数的指针的函数声明将变得复杂。例如,这个声明:

porder h( void );

没有使用typedef的话,它看起来像这样:
int ( *h( void ) )( void *, void * );

@Lundin,我展示了这个例子,因为在glglgl的答案中,显示了一个无效的typedef构造,适用于两个声明符。 - Vlad from Moscow
但你永远不会把它们写在同一行上。 - Lundin
@Lundin 保持冷静。语法训练练习对于更好地理解语言结构非常重要。 - Vlad from Moscow
如果你不指出某些语法是不好的实践,那么很快你就会发现新手写出像 int* x, (*y)(int), z; 这样的代码。 - Lundin
是的,即使一个经验丰富的程序员都无法正确使用它,这就说明该语法有多么糟糕和不常用。 - Lundin
你最后的例子很有用...我在OpenSSL中发现了一些返回函数指针的函数声明,但是我根本无法理解。 - zentrunix

2

你可以执行以下任一操作:

typedef int (*order) (void *, void *);
typedef int order(void *, void *);

根据您想要typedef函数还是指针的情况而定。

两种方法都有优缺点;我更喜欢一种风格,其中指针作为指针可见,并且我的函数定义为

order order_impl;
int order_impl(void * a, void * b)
{
}
order * order_pointer = order_impl;

这可以确保函数被正确定义。
然而,有些人更喜欢使用函数指针类型并进行操作。
porder order_pointer = order_impl;

在没有这种保护的情况下生活,只留下警告而不是错误提示,以防出现不匹配的情况。


2
您可以像声明函数一样声明函数指针,只需将函数名括在括号中,并在名称前面添加*即可。
void func (void);              // function
void (*func) (void);           // pointer to function
typedef void (*func) (void);   // pointer to function type

然而,我推荐的风格是不要在 typedef 后面隐藏指针:

typedef int order_t (void*, void*);
...
order_t* order; 
< p > typedef 是一个函数模板,声明是该类型的函数指针声明。这使函数指针语法与对象指针一致。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接