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?
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
.