RedditPP Mascot

RedditPP

r/C_Programming • … • u/LemonLord7

Performance loss of mimicing interfaces with function pointers on modern compilers?

C does not have interfaces like languages such as C# or C++, but the cocnept can be mimicked by using function pointers. You might for instance have this:

// fruit_interface.h

typedef struct fruit_vtable { float (*get_weight)(void *object); float (*get_density)(void *object); const char *(*get_name)(void *object); } fruit_vtable;

typedef struct fruit_interface { void *object; const fruit_vtable *vtable; } fruit_interface;

// banana.h

typedef struct banana { float weight; float density; } banana; fruit_interface banana_as_fruit(banana *b);

--------------------------

// banana.c

static float banana_get_weight(void *object) { banana *b = (banana*)object; return b->weight; }

static float banana_get_density(void *object) { banana *b = (banana*)object; return b->density; }

static const char *banana_get_color(void *object) { (void)object; return "yellow"; }

static const fruit_vtable banana_vtable = { .get_weight = banana_get_weight, .get_density = banana_get_density, .get_color = banana_get_color, };

fruit_interface banana_as_fruit(banana *b) { return (fruit_interface) { .object = (void*)b, .vtable = &banana_vtable }; }

--------------------------

// main.c

static void print_fruit(fruit_interface fruit) { printf("weight: %.2f g\n", fruit.vtable->get_weight(fruit.object)); printf("density: %.2f g/cm^3\n", fruit.vtable->get_density(fruit.object)); printf("color: %s\n", fruit.vtable->get_color(fruit.object)); }

int main(void) { banana b = { .weight = 120.0f, .density = 0.95f };

fruit_interface fruit = banana_as_fruit(&b);

print_fruit(fruit);

return 0; }

How does something like this affect performance in terms of speed and cpu usage but also memory? I know modern C compilers can be really powerful and do a lot of optimizations and even more so with link time optimizations.

Of course it depends on the bigger project as a whole, and I understand that a if you have thousands of fruit\_interface variables that all point to many different fruit\_vtables and are used many times per second/cycle, then that will be very different from e.g. a hardware\_interface that just loads some data once in an initialization function at program start.

The question here is pretty open (and the above is just to show clearly what I mean), and I am mostly looking for some general knowledge and guidance for when something like this is good and when it is bad, especially in the context of modern C code development with modern compilers and linkers.

I think it is really interesting to see how concepts in other languages, like C++, can be handled in C and what C is capable!

— 0