C函数声明可以有多个标识符吗?

C函数声明可以有多个标识符吗?,c,signals,function-pointers,typedef,C,Signals,Function Pointers,Typedef,示例3中有一个C函数声明信号: void (*signal(int, void (*fp)(int)))(int); 我想知道怎么会有两个标识符signal,fp,它仍然通过编译(我在现有代码中随机添加了这一行,它成功编译了)?名称fp通常用于FILE*类型的变量,但它可以用于各种其他用途(浮点、渔业保护、函数指针等) 问题中的函数声明与C标准中的声明相同,只是它使用了fp,其中标准使用了func,并且标准为sig的第一个参数指定了名称sig 您可以从函数声明(原型)中删除fp;无重大更改:

示例3中有一个C函数声明
信号

void (*signal(int, void (*fp)(int)))(int);

我想知道怎么会有两个标识符
signal
fp
,它仍然通过编译(我在现有代码中随机添加了这一行,它成功编译了)?

名称
fp
通常用于
FILE*
类型的变量,但它可以用于各种其他用途(浮点、渔业保护、函数指针等)

问题中的函数声明与C标准中的声明相同,只是它使用了
fp
,其中标准使用了
func
,并且标准为
sig
的第一个参数指定了名称
sig

您可以从函数声明(原型)中删除
fp
;无重大更改:

void (*signal(int, void (*)(int)))(int);
您还可以在整个过程中为参数使用有意义的名称:

void (*signal(int signum, void (*handler)(int signum)))(int signum);
每次出现的
signum
标识提供信号号的位置。
signal()的第一个参数
本身是一个信号号;
handler
的参数表示将使用信号号调用处理函数;最外面的
signum
表示
signal()
返回的函数指针与
handler
的类型相同,应该是(is)呼叫时传递了一个信号号码


另请参见。

名称
fp
通常用于
FILE*
类型的变量,但它也可用于各种其他用途(浮点、渔业保护、函数指针等)

问题中的函数声明与C标准中的声明相同,只是它使用了
fp
,其中标准使用了
func
,并且标准为
sig
的第一个参数指定了名称
sig

您可以从函数声明(原型)中删除
fp
;无重大更改:

void (*signal(int, void (*)(int)))(int);
您还可以在整个过程中为参数使用有意义的名称:

void (*signal(int signum, void (*handler)(int signum)))(int signum);
每次出现的
signum
标识提供信号号的位置。
signal()的第一个参数
本身是一个信号号;
handler
的参数表示将使用信号号调用处理函数;最外面的
signum
表示
signal()
返回的函数指针与
handler
的类型相同,应该是(is)呼叫时传递了一个信号号码


另请参见。

否,C函数声明/原型不能有多个标识符。请参阅cplusplus.com上的参考页和信号示例代码:

在本宣言中:

void (*signal(int sig, void (*func)(int)))(int);
我们正在声明一个名为
signal
的函数,它返回一个指向函数的指针,该函数返回
void
,并接受一个
int
——即:指向如下函数的指针:

void func(int);
信号
函数的输入是1,一个
int
,2,一个指向函数的指针,该函数返回一个
void
,并接受一个
int
——同样,一个指向类似上述
func
函数的指针。现在,在C中,当声明一个函数时,该函数返回一个指向函数的指针,并接受一个指向函数的指针在一开始,它看起来很傻(看起来乱七八糟),这就是为什么我们一开始都很困惑(而且一次又一次频繁)查看函数声明,如
signal
。在C中定义函数,如
signal
,有两种更清晰的方法,让这一切都清晰明了,它们都是这样的,而这两种方法都与看起来呆滞呆滞的方法相同:

// 1. typedef a function--call it `func_t` for "func type"
typedef void func_t(int);

// 2. Use the typedef above to define `signal`
func_t* signal(int sig, func_t* fp); // Ah, now this makes sense!

记住,函数声明中的每个输入参数类型在C中都是无关的,甚至不必在头文件和源文件之间匹配。

例:

my\u模块.h:

// Any of these 3 prototypes are equivalent, valid, and identical
// (although using sensible names which match between the header &
// source files is most clear and helpful to the reader!):
func_p signal(int sig, func_p fp);
func_p signal(int signal, func_p whatsupdude);
func_p signal(int, func_p);
func_p signal(int sig, func_p fp)
{
    // define the function here
}
my_模块.c:

// Any of these 3 prototypes are equivalent, valid, and identical
// (although using sensible names which match between the header &
// source files is most clear and helpful to the reader!):
func_p signal(int sig, func_p fp);
func_p signal(int signal, func_p whatsupdude);
func_p signal(int, func_p);
func_p signal(int sig, func_p fp)
{
    // define the function here
}
现在,我最初是如何理解这一切的?
答:我看了。这有助于把这一切弄清楚,因为你可以看到
信号的返回值是如何分配给
prev\u handler
,它是一个函数的指针,你可以看到
my\u handler
,它被定义为一个函数,是如何作为第二个参数传递给
信号的d可能还提到,这两行是相同的,并且都是完全有效的:

prev_handler = signal (SIGINT, my_handler);
prev_handler = signal (SIGINT, &my_handler);
这是因为,如果您将函数作为参数传入,编译器知道无论如何只需获取其地址

/*信号示例*/
#包括/*printf*/
#包括/*信号、上升、信号*/
sig_原子信号=0;
作废我的_处理程序(int参数)
{
信号=1;
}
int main()
{
无效(*上一页)(整数);
prev_handler=信号(SIGINT,my_handler);
/* ... */
升起(SIGINT);
/* ... */
printf(“发出信号的是%d.\n”,发出信号的);
返回0;
}
参考资料:
  • 关于如何键入定义函数和函数指针的提示,因为这几乎让所有人都感到困惑,并且需要不时重新验证:

  • 否,C函数声明/原型不能有多个标识符。请参阅cplusplus.com上的参考页和信号示例代码:

    在本宣言中:

    void (*signal(int sig, void (*func)(int)))(int);
    
    我们正在声明一个名为
    signal
    的函数,它返回一个指向函数的指针,该函数返回
    void
    ,并接受一个
    int
    ——即:指向如下函数的指针:

    void func(int);
    
    信号
    函数的输入是第一个
    int
    ,第二个是指向函数的指针,该函数返回
    void
    ,并接受
    int
    ——同样,是指向上面类似
    func
    的函数的指针