当声明为结构字段内的字段时,void(func)(void)和void(*func)(void)之间的区别是什么?

brccelvz  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(199)

所以我被告知这两个几乎一模一样

void function1 (void(func)(int), int arg){
    func(arg);
}

void function2 (void(*func)(int), int arg){
    func(arg);
}

当我执行它时,它不会抛出错误。

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);

}

但是当我在一个结构体内部初始化相同的void(unc)(int)vs void(* unc)(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;
}

它抛出编译器错误?

error: field 'func1' declared as a function
    void (func1)(int);

为什么void(func)(void)作为回调函数编写时有效,而作为结构体中的字段编写时无效?

fcg9iug3

fcg9iug31#

名义上,void (func)(int)声明了一个函数,它接受int并且不返回任何东西,而void (*func)(int)声明了一个指向这样一个函数的指针。
在标准基C中,函数不是对象。它们不能赋值给变量,不能作为参数传递,也不能存储在结构成员中。
然而,C 2018 6.7.6.3第8期称:
参数声明为“返回 * 类型 * 的函数”时,应调整为“返回 * 类型 * 的函数指针",如6.3.2.1所示。
这意味着,当你将一个参数声明为函数时,它会自动更改为将该参数声明为指向函数的指针。在C标准中没有任何内容要求在声明结构成员时进行此调整。这就是为什么名义上(而不是实际上)可以将函数参数声明为函数,但不能将结构成员声明为函数的原因。

相关问题