函数指针声明

Function Pointer Declaration

与我在网上找到的示例、SO 答案和教程相比,我对我使用的教科书有点困惑。

书中的代码声明了两个函数指针,但从未给它们赋值,并且在声明中没有使用 *。代码运行良好,编译时没有警告,所以我有点困惑。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{   
    void    f(int), g(int);

    signal(SIGUSR1, f);
    signal(SIGUSR2, g);

    while(1)
        sleep(1);
}   

void f(int signum)
{   
    printf("Recieved signal %d: SIGUSR1\n", signum);
}   

void g(int signum)
{   
    printf("Received signal %d: SIGUSR2\n", signum);
    exit(SIGUSR2);
}   

我在网上找到的代码看起来都与此类似,指针语法 * 并且将函数地址显式分配给函数指针:

#include <stdio.h> 

void fun(int a) 
{ 
    printf("Value of a is %d\n", a); 
} 
  
int main() 
{ 
    void (*fun_ptr)(int) = &fun; 
  
    (*fun_ptr)(10); 
  
    return 0; 
} 

是否有不止一种声明函数指针的正确方法?

为什么书中的代码有效?

一个版本比另一个版本“更正确”吗?

这个声明

void    f(int), g(int);

在函数 main 的块范围内声明了两个函数 fg。它们可以在 main 之前声明,但代码的作者决定在 main 中声明它们,因为它们只在 main 中使用。所以没有函数指针的声明。

看来你对函数声明的地方搞糊涂了

为了更清楚,您可以按以下方式重写程序

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void    f(int), g(int);

// or

void f(int);
void g(int);

int main(int argc, char *argv[])
{   
    signal(SIGUSR1, f);
    signal(SIGUSR2, g);

    while(1)
        sleep(1);
}   

void f(int signum)
{   
    printf("Recieved signal %d: SIGUSR1\n", signum);
}   

void g(int signum)
{   
    printf("Received signal %d: SIGUSR2\n", signum);
    exit(SIGUSR2);
}

尽管编译器会发出一条消息,指出存在冗余函数声明,但该程序是有效的。

这些语句中使用的函数指示符

signal(SIGUSR1, f);
signal(SIGUSR2, g);

被编译器隐式转换为指向函数的指针。

void f(int), g(int); 不声明函数指针*。它声明了两个函数(f接受int并返回voidg接受int并返回void)。

void (*f)(int), (*g)(int); 会声明相应的函数指针,这些函数指针确实需要在使用前进行一些初始化。)

在块范围内声明函数有点令人困惑,因为函数不能是块局部的。

实际上就好像你在文件范围内有 void f(int); void g(int);,只是块范围限制了前向声明的范围:

示例:

void call_f(void)
{
    void f(int);
    f(42);
}

void call_f_again(void)
{
    void f(int); //need to redeclare unless there's also a global decl for f
    f(42);
}

但是当涉及到函数时,这个范围限制实际上没有任何作用,因为所有这些重新声明必须相互兼容并与相应的文件范围声明(无论是否提供)相兼容。

在文件范围简单地声明函数是最简单的(也是最不容易混淆的)。


  • void f(int) 仅在用作函数参数时等同于 void (*f)(int)。这类似于函数参数中的 int f[] 等价于 int *f.
  • 的方式