Search code examples
cfunctionstructprefix

Function Prefix vs "Function Struct" in C


I'm trying to figure out best practices in C(11). Because there are no namespaces I can think of two approaches to avoid name collisions:

a.) Function prefixes

void kernel_init(void) { ... }
int kernel_start(void* foo) { ... }

b.) "Function structs"

struct kernel {
    void (*init)(void);
    int (*start)(void* foo);
} kernel;

I'm not asking which approach is prettier because that's rather subjective. What I'm asking is are there any noticeable downsides to either approach apart from code style? This includes little things that are irrelevant at first but become larger problems once the code base grows.


Solution

  • Interesting, I had never thought of that solution before.

    The first one is of course standard, and I'd bet that's what you would find in the vast majority of C projects[*].

    The second in theory takes memory, since you're actually declaring a data object full of function pointers. You would of course also need to initialize the kernel variable, i.e. have something like:

    ...
    } kernel = {
      .init = kernel_init,
      .start = kernel_start,
    };
    

    But oooh there you go with prefixed functions again. To remove the need for those, the functions have to be static, which I guess is possible if you add extern to the struct declaration in the kernel.h.

    So a more complete example could be:

    // kernel.h (public header)
    typedef struct kernel_api {
      void (*init)(void);
      int (*start)(void* foo);
    } kernel_api;
    
    extern const kernel_api kernel;
    
    // in kernel.c
    static void init(void)
    {
      ...
    }
    
    static int start(void *foo)
    {
      ..
    }
    
    const kernel_api kernel = {
      .init = init,
      .start = start,
    };
    

    This might work, but I haven't tried it.

    Finally, having explicit data means it takes a sufficiently smart compiler to optimize those out and make more direct calls, but I haven't tried it and it's a bit risky to depend on such. Interesting.

    [*] I think I just statistically claimed that I have seen (or thought of) the vast majority of the world's C projects, but that's of course not true. :)