所以我被告知这些几乎彼此相同
void function1 (void(func)(int), int arg){
func(arg);
}
void function2 (void(*func)(int), int arg){
func(arg);
}
Run Code Online (Sandbox Code Playgroud)
当我执行这个时,它不会抛出任何错误。
void print_plus_1(int p)
{
printf("p=%d\n", p+1);
}
void print_plus_2(int p)
{
printf("p=%d\n", p+2);
}
int main(void)
{
function1(print_plus_1, 1);
function2(print_plus_2, 1);
}
Run Code Online (Sandbox Code Playgroud)
但是,当我在结构内初始化相同的 void (func) (int) 与 void (*func) (int) 模式时
struct foo
{
void (func1)(int);
void (*func2)(int);
};
void print_plus_1(int p)
{
printf("p=%d\n", p+1);
}
void print_plus_2(int p)
{
printf("p=%d\n", p+2);
}
int main(void)
{
struct foo f;
f.func1 = print_plus_1;
f.func2 = print_plus_2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它会抛出编译器错误吗?
error: field 'func1' declared as a function
void (func1)(int);
Run Code Online (Sandbox Code Playgroud)
为什么 void (func)(void) 当写为回调函数而不是作为结构体内部的字段时可以工作?
名义上,void (func)(int)声明一个接受 anint且不返回任何内容的函数,并void (*func)(int)声明一个指向该函数的指针。
在标准 C 语言中,函数不是对象。它们不能分配给变量、作为参数传递或存储在结构成员中。
\n然而,C 2018 6.7.6.3 8 说:
\n\n\n将参数声明为 \xe2\x80\x9c 返回类型\xe2\x80\x9d 的函数应调整为 \xe2\x80\x9c 指向返回类型\xe2\x80\x9d 的函数的指针,如 6.3.2.1 中所示。
\n
这意味着,当您将参数声明为函数时,它会自动更改为将参数声明为函数指针。C 标准中没有任何内容规定在声明结构成员时进行此调整。这就是为什么您可以名义上(但实际上不是)将函数参数声明为函数,但不能将结构成员声明为函数。
\n