用预处理器展开PySpam_System
,你会看到:
(*(int (*)(const char *command)) PySpam_API[0])
该表达式(或多或少)是对“返回 int 并采用一个类型const char *
的参数的函数的指针”的强制转换。之后必须("something")
通过指向函数的指针将整体转换为函数调用。因此,在代码中,您可能会看到:
PySpam_System("abc");
编译器会看到:
(*(int (*)(const char *command)) PySpam_API[0])("abc");
那是对存储在PySpam_API
索引位置 0 的数组中的函数的调用。显然,参数可能不是简单的字符串文字,但简单的字符串文字是一个代表const char *
。
问题更新
为什么const char *command
,不只是const char *
。我认为在函数指针类型声明和类型转换中应该省略参数的名称?所以一定不能省略,而只是可以?
参数的名称(例如command
在示例中)在原型声明中是可选的。也没有规定原型声明中的名称必须与函数定义中的名称匹配。遗憾的是,如果您编写函数以符合接口但函数的特定实现不需要参数,则 C 尚未采用 C++ 约定,即名称在函数定义中是可选的。也就是说,在 C++ 中,您可以编写:
typedef int (*interface)(const char *cmd, int arg1, int arg2);
static int implementation(const char *cmd, int arg1, int) // C++, not C
{
return some_other_function(cmd, arg1, 23, 19);
}
该函数implementation
符合interface
类型,但不使用arg2
参数,但编译器不会抱怨未使用的参数。C 不允许这种便利性,因此即使您非常清楚它未使用,您也会被告知“未使用的参数”。我相信有一些特定于编译器的方法可以解决这个特定问题。
为什么(*(int (*)(const char *command))
,不只是(int (*)(const char *command)
?外挂的目的是(*[everything else here])
什么?这是对函数本身的函数指针的可选取消引用,对吗?
对。
请注意,通过函数指针调用函数有两种方法,大致是“旧”和“新”(其中新的意思是“由 C89 标准引入和祝福”,因此它不完全是“新”)。
所需的旧符号(提供或获取当时不可用的原型):
#include <math.h>
double (*func)(double) = sin;
double x = (*func)(1.0);
带括号和*
函数指针。这个想法是,如果你有一个指向函数的指针,你需要取消引用它来调用函数。更现代的表示法指出,函数的名称变成了指向函数的指针(例如在赋值中),因此您实际上并不需要这种(*func)
表示法。因此,较新的样式是:
#include <math.h>
double (*func)(double) = sin;
double x = func(1.0);
由于我在旧式是强制性的时候学习了 C,所以我仍然更喜欢稍微冗长但完全明确的表示法。宏中的代码PySpam_System
也使用旧的表示法。
您还可以使用函数指针玩各种愚蠢的游戏,添加额外的*
和使用 a &
,所有这些都是不必要的。
double (*funca)(double) = &sin;
double (*func0)(double) = sin;
double (*func1)(double) = *sin;
double (*func2)(double) = **sin;
double (*func3)(double) = ***sin;
只有func0
声明是明智的;其余的都是模糊的 C.