Is it possible/safe/sane to pass around a function pointer to a static function?

1.6k Views Asked by At

Let’s say I only want to expose a function from one of my files by passing out a function pointer to that function. Is it safe to declare that function as static? Are compilers allowed to do any judo that would invalidate my function pointer, or make it meaningless outside the context of that file, since the function is declared as specific to that file?

Not my code, but a (silly) example of what I mean:

void    static   cool_function(void);
void    extern (*cool_function_ptr)(void); // Actually, I’m not sure of where the `extern` goes in a function-
                                           // pointer declaration. Damn you, confusing function-pointer syntax!

Given that code (or the syntactically correct approximation thereof), would it be illegal to access cool_function_ptr from another file?

5

There are 5 best solutions below

3
On BEST ANSWER

It is completely safe to do so, and often useful. The same goes for static variables and data pointers. If the compiler wants to do any fancy optimizations (like nonstandard calling conventions, inlining, refactoring, etc.) that could interfere with the ability to call the function through a function pointer from a different translation unit, it's the compiler's responsibility to either determine that the address of the function is never taken, or to generate multiple versions of the code, one of which is safe to be called from outside with the standard calling convention.

2
On

Sure. A function pointer is just an address, there's nothing magical about it.

Here's an example:

$ cat Makefile
.PHONY: all
all:    main
        ./main
main:   main.c other.c 
        gcc -o main main.c other.c 
$ cat main.c
#include <stdio.h>

static void goodnight(){
  printf("Goonight, gracie!\n");
  return;
}

int
main(char * argv[], int argc){
  other(goodnight);
  return 0;
}
$ cat other.c
#include <stdio.h>

void other(void(*fp)()){
  fp();
  return ;
}
$ make
gcc -o main main.c other.c 
./main
Goonight, gracie!
$ 

The hard part is getting the declaration of a function taking a pointer to function returning void right.

5
On

The only thing that might bite you is if the function is inlined -- and taking the address of it for a pointer should keep that from happening.

Doing this kinda keeps the caller from knowing the full signature, so you're playing with fire and hoping things line up though.

And it's "extern void" and "static void" -- storage class, then return type.

0
On

There's nothing different about a pointer to a static function.

However, passing the pointer around may be slightly less efficient than allowing it to be called directly. It wasn't entirely clear to me why you're doing that, but it didn't make much sense to me.

0
On

Definitely allowed, potentially perfectly reasonable


The language allows you to pass a pointer to a static function outside of a module.

Therefore, any tricks that the compiler might do in compiling intra-module calls must somehow be compatible with what you are doing.

In general, I would say it's actually a good code pattern, relative to making the function global, because you are additionally encapsulating the function, although one could make the opposite argument with respect to a simple static function with no external references.

All-in-all, I think it's the design of your objects and your application that matters, and not whether you globally reference a static function.