typedef void (*print_type) (const char*);
typedef void (*print_type) (const char*);
在探索一些代码时,我在头文件中发现了以下内容:
typedef void (*print_type) (const char*);
这行是什么意思?我知道 typedef
用于使特定词(在我们的例子中是 *print_type
)来表示特定的类型(在我们的例子中是 const char*
)。
但我的问题是为什么我们必须使用 void
?
这是什么?
typedef void (*print_type) (const char*);
typedef 告诉编译器数据类型 print_type
是一个指向接受 const char*
作为参数但不 return 值的函数的指针。
...而且它与 DLL 无关
函数指针
我们声明一个函数如下:
ret-type identifier(parameters)
int f(double x)
鉴于对于声明为int a
的东西,指向它的指针被声明为int *a
(在数据类型后加一个*),自然会有人想出办法声明一个函数指针如下:
int *f(double);
这里有一个陷阱。这实际上是一个函数的声明,它接受一个 double
作为参数并且 return 是一个 int*
.
我们需要明确地告诉编译器它不是一个函数 returning 一个指针;相反,它是一个指向函数的指针。我们通过在 *f
.
周围放置括号(括号具有更高的优先级)来做到这一点
int (*f)(double);
再举个例子:
int* myfunc(int a[], char b);
要声明指向具有上述签名的函数的函数指针数组,我们这样写:
int* (*ptr[])(int[], char);
有一个叫做 Spiral Rule 的技巧,它在找出什么是复杂的数据类型时非常有用。
使用类型定义
函数指针会使事情变得相当复杂。为了保持代码的可读性和整洁性,我们更喜欢使用 typedef 为函数指针类型提供单个符号类型名称。
typedef int (*ptrFunc_t)(int, char);
这允许您声明一个指向接受 int
和 char
作为参数以及 return 和 int
的函数的指针,如下所示:
ptrFunc_t myptr;
它正在创建指向函数的指针的类型定义,该函数采用 const char 指针参数并且不返回任何内容。
此类 typedef 在用于动态加载的库中很常见(即 LoadLibrary 等),因为您必须将函数指针加载到实际函数,而不是像 load 那样直接使用函数名-时间链接。
这个:
void foo(const char*);
将 foo
声明为一个接受 const char*
参数和 returns void
的函数(即,它不 return 任何东西)。 (必须在某处定义它才能调用它。)
这个:
void (*bar)(const char*);
定义bar
为指针对象。它是指向与上面 foo
具有相同类型的函数的指针。
通过添加 typedef
关键字,这:
typedef void (*print_type)(const char*);
定义print_type
,不是作为函数指针类型的对象,而是作为函数指针类型的别名。
在探索一些代码时,我在头文件中发现了以下内容:
typedef void (*print_type) (const char*);
这行是什么意思?我知道 typedef
用于使特定词(在我们的例子中是 *print_type
)来表示特定的类型(在我们的例子中是 const char*
)。
但我的问题是为什么我们必须使用 void
?
这是什么?
typedef void (*print_type) (const char*);
typedef 告诉编译器数据类型 print_type
是一个指向接受 const char*
作为参数但不 return 值的函数的指针。
...而且它与 DLL 无关
函数指针
我们声明一个函数如下:
ret-type identifier(parameters)
int f(double x)
鉴于对于声明为int a
的东西,指向它的指针被声明为int *a
(在数据类型后加一个*),自然会有人想出办法声明一个函数指针如下:
int *f(double);
这里有一个陷阱。这实际上是一个函数的声明,它接受一个 double
作为参数并且 return 是一个 int*
.
我们需要明确地告诉编译器它不是一个函数 returning 一个指针;相反,它是一个指向函数的指针。我们通过在 *f
.
int (*f)(double);
再举个例子:
int* myfunc(int a[], char b);
要声明指向具有上述签名的函数的函数指针数组,我们这样写:
int* (*ptr[])(int[], char);
有一个叫做 Spiral Rule 的技巧,它在找出什么是复杂的数据类型时非常有用。
使用类型定义
函数指针会使事情变得相当复杂。为了保持代码的可读性和整洁性,我们更喜欢使用 typedef 为函数指针类型提供单个符号类型名称。
typedef int (*ptrFunc_t)(int, char);
这允许您声明一个指向接受 int
和 char
作为参数以及 return 和 int
的函数的指针,如下所示:
ptrFunc_t myptr;
它正在创建指向函数的指针的类型定义,该函数采用 const char 指针参数并且不返回任何内容。
此类 typedef 在用于动态加载的库中很常见(即 LoadLibrary 等),因为您必须将函数指针加载到实际函数,而不是像 load 那样直接使用函数名-时间链接。
这个:
void foo(const char*);
将 foo
声明为一个接受 const char*
参数和 returns void
的函数(即,它不 return 任何东西)。 (必须在某处定义它才能调用它。)
这个:
void (*bar)(const char*);
定义bar
为指针对象。它是指向与上面 foo
具有相同类型的函数的指针。
通过添加 typedef
关键字,这:
typedef void (*print_type)(const char*);
定义print_type
,不是作为函数指针类型的对象,而是作为函数指针类型的别名。