Search code examples
cfunction-pointersimplicit-conversionfunction-declaration

Function Pointer Declaration


I'm a little confused by the textbook I'm using compared to examples, SO answers, and tutorials I've found online.

The code from the book declares two function pointers but never assigns a value to them, and it doesn't use * in the declaration. The code runs fine and compiles without warning, so I'm a little confused.

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

The code that I've found online all looks similar to this, with pointer syntax * and an explicit assignment of a function address to the function pointers:

#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; 
} 

Is there more than one correct way to declare a function pointer?

Why does the code from the book work?

Is one version "more correct" than the other?


Solution

  • void f(int), g(int); doesn't declare function pointers*. It declares two functions (f taking int and returning void, and g taking int and returning void).

    (void (*f)(int), (*g)(int); would declare the corresponding function pointers and those would indeed require some initialization before use.)

    Declaring functions in a block scope is a little bit confusing because functions cannot be block-local.

    In effect it's as if you had void f(int); void g(int); in filescope, except the block scope limits the scope of the forward declarations:

    Example:

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

    but this scope limitation doesn't really do anything when it comes to functions as all such redeclarations have to be compatible with each other and with a corresponding filescope declaration (whether or not it's provided).

    It's simplest (and least confusing) to simply declare functions at filescope.


    • void f(int) is only equivalent to void (*f)(int) when it's used as a function paramater. This is similar to how int f[] in a function parameter is equivalent to int *f.