C语言 奇怪的typedef声明

0qx6xfy6  于 2023-03-07  发布在  其他
关注(0)|答案(2)|浏览(175)

我在/usr/include/png.h中看到一个类型定义声明

typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp));

我看不懂这份声明。
这是函数指针返回函数指针吗?
谢谢!

cclgggtu

cclgggtu1#

这是一个函数指针别名声明。C中的函数指针类型定义(和类型转换)使用以下语法:return_type (optional_calling_convention* identifier)(args).
在本例中,png_error_ptr变成了一个函数指针的别名,该函数使用PNGAPI调用约定返回void并接受PNGARG((png_structp, png_const_charp))参数。
PNGARG是一个函数类型宏,定义为#define PNGARG (x) xpng_structppng_const_charp是类型,它扩展为typedef void (PNGAPI *png_error_ptr) (png_struct *, const char *),您可能更容易理解为指向函数的指针,如下所示:void PNGAPI func(png_struct *arg1, const char *arg2).希望这对你有帮助!
编辑:在here中可以找到针对没有经验的人的更详细的解释

xjreopfe

xjreopfe2#

这在libpng中使用。首先,您应该解析宏:
PNGAPI__cdecl__stdcall的占位符,即调用约定。
PNGARG是一种解决方案,可以科普非常老的编译器,这些编译器没有原型,在正常的编译器中,它只是参数。
因此,我们只剩下:

typedef void (*png_error_ptr)(png_structp, png_const_charp);

你从左到右阅读,你得到了typedef,所以我们定义了一个新的类型,然后你得到了void,所以我们看的是void的定义,它会是什么呢?,指针或者一个什么都不返回的函数,我们继续。
接下来是(*png_error_ptr),这是png_error_ptr的定义,它是一个指针,这可能是一个新类型的定义,一个指针的别名,但是我们有更多的东西,我们在右边有一个左括号,所以png_error_ptr是返回void的函数指针的别名,这与前面的注解一致:

/* These are the function types for the I/O functions and for the functions
 * that allow the user to override the default I/O functions with his or her
 * own.  The png_error_ptr type should match that of user-supplied warning
 * and error functions, while the png_rw_ptr type should match that of the
 * user read/write data functions.
 */

我们能不能再多说一些关于这个函数所期望的参数类型的内容?好的,我们有:

typedef PNG_CONST char  FAR * png_const_charp;
typedef png_struct FAR * png_structp;

更难看的宏。但这些是为非常奇怪/旧的编译器准备的。通常你会有:

#define PNG_CONST const
#define FAR

所以

typedef const char * png_const_charp;
typedef png_struct * png_structp;

综合考虑,您可以假设:

typedef void (*png_error_ptr)(png_struct *, const char *);

如果你想为参数取一些合理的名字,你可以查看pngerror.c文件,它提供了(作者的话)“用于i/o和内存分配的存根函数”:

typedef void (*png_error_ptr)(png_struct *png_ptr, const char *error_message);

基本上,这是png_set_error_fn()初始化时可以提供的函数类型,它将png_ptr->error_fn设置为函数指针。
自定义错误函数应类似于:

void my_custom_error_function(png_struct *png_ptr, const char *error_message);

所有这些工作都是为了支持旧的编译器,特别是那些来自DOS时代的、具有奇怪内存模型的编译器。

相关问题