为什么声明函数参数而不是函数指针参数是允许的?

问题描述 投票:0回答:3

我真的不知道我希望得到什么答案,但是能够声明函数参数而不能以相同的方式在函数内声明变量让我感到不安。

#include <stdio.h>

void func(void why_is_this_allowed()) {
    why_is_this_allowed();
}

void func2(void (*this_makes_more_sense)()) {
    this_makes_more_sense();
}

void print() {
    printf("I am stuff\n");
}

int main()
{
    void and_why_is_this_NOT_allowed() = print;
    
    func(print);
    func2(print);

    return 0;
}
c function-pointers implicit-conversion function-declaration
3个回答
1
投票

编译器将具有函数类型的函数参数调整为指向函数类型的指针。所以这两个函数声明

void func(void why_is_this_allowed());

void func(void (*why_is_this_allowed)());

声明相同的功能。

另一方面,表达式中使用的函数指示符被隐式转换为指向函数类型的指针。

考虑例如这个代码片段

void f( void )
{
}

//...

void ( *pf )( void ) = f;

在此代码片段中,用作初始值设定项的函数指示符

f
被隐式转换为指向函数的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

4 函数指示符是具有函数类型的表达式。 除非它是 sizeof operator65) 的操作数或一元 & 运算符,类型为“函数返回类型”的函数指示符 转换为类型为“指向函数的指针”的表达式 返回类型''。

和(6.7.6.3 函数声明符(包括原型))

8 将参数声明为“函数返回类型”应该是 调整为“指向函数返回类型的指针”,如 6.3.2.1.

这条线

void and_why_is_this_NOT_allowed() = print;

没有意义,因为与指针声明相反的函数声明不声明对象。所以函数说明符声明的初始值设定项没有意义。

和写一样

int x;

int = x;

如您所见,最后一行在语法上是无效的。


0
投票

就像数组作为参数调整为指针一样,函数作为参数调整为函数指针。

这在 C 标准的第 6.7.6.3p8 节中有详细说明

将参数声明为“函数返回类型”应该是 调整为“指向函数返回类型的指针”,如 6.3.2.1.

这意味着:

void func(void why_is_this_allowed()) {
    why_is_this_allowed();
}

和这个一模一样:

void func(void (*why_is_this_allowed)()) {
    why_is_this_allowed();
}

相比之下,这行不通:

void and_why_is_this_NOT_allowed() = print;

因为没有这样的调整发生,所以

and_why_is_this_NOT_allowed
被认为是函数声明,而这样的声明不是左值,因此不能赋值。


0
投票

我真的不知道为什么它会这样工作,但这是声明和使用函数指针的正确方法:

#include <stdio.h>

void func(void why_is_this_allowed()) {
    why_is_this_allowed();
}

void func2(void (*this_makes_more_sense)()) {
    this_makes_more_sense();
}

void print() {
    printf("I am stuff\n");
}

int main()
{
    // function pointer declaration and initialization
    void (*and_why_is_this_NOT_allowed)(void) = &print;

    func(print);
    func2(print);

    // calling the function
    and_why_is_this_NOT_allowed();
    return 0;
}

希望这对您有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.