Search code examples
cstructclangassign

Assign value to struct array without function


I am currently working on a device manager but encountered a problem... As shown i declared a struct array which is supposed to hold the writer function of a device (vga, serial)... The main issue is that i don't want to call an initialize function, e.g vga_init() or serial_init() to assign them to the structure, tbh that would lose sense... Rather i wanna have those functions stored in an struct array, is there a way to assign vga_write/serial_write without a function, like shown below (Notice the two comments)?

Thanks for incoming advices!

/* device.h */

#define vga    0
#define serial 1

/* device info structure */

struct device_io {
    void (*write)(const char *str);
}

extern struct device_io *io[];


/* vga.c */

io[vga] = { .wr = &vga_write };           // Won't work!
void vga_write(const char *str) { ...

/* serial.c */

io[serial] = { .wr = &serial_write };     // Won't work also!
void serial_write(const char *str) { ...

Solution

  • Outside of a function you can only use an initializer expression to assign a value to a global (or static or bss) variable.

    That in turn means the initializer expression you're using must initialize the entire array at once, like so:

    static int test[] = { 4, 5, 6 };
    

    , which, of course, can be extended to arbitrary data like function pointers or structs

    void some_func0(const char *v) { }
    void some_func1(const char *v) { }
    static void (*test[])(const char *) = { &some_func0, &some_func1 };
    

    . As you can see though, this requires that all the functions you intend to use are at least declared before the initializer. At the point of declaration of the array in your question (in "device.h") I presume you don't know all implementations.

    However, you need to have a source file somewhere in your program where you do know all array elements at once. To work around this, you can restructure your code like:


    device.h

    extern void (*test[])(const char *); // <-- or your struct type
    

    vga.h

    extern void vga_write(const char *);
    

    vga.c

    void vga_write(const char *c) {...
    

    device_array_initialization_helper_this_is_a_very_verbose_file_name.c

    #include "device.h"
    #include "vga.h"
    
    // Definition of the array, which is declared in device.h
    void (*test[])(const char *) = { &vga_write, ... };
    

    Of course, you can use your struct type as well.