Type-Safe Wrappers: Macros That Protect Your void*
Post 5 of the Dynamic Arrays in C series · Full source code on GitHub The Ergonomics Problem Post 4 left us with a working generic array. One struct, one push function, one get function, stores any fixed-size type. The void* engine works. But using it is miserable. To push an integer, you can’t just write array_push(arr, 42). You have to create a variable, then pass its address: int x = 42; array_push(arr, &x);. Two lines for something that should be one expression. To read a value back, you get a void* that you must cast manually: int *val = (int *)array_get(arr, 0);. Every access requires a cast. Every cast is an opportunity to lie to the compiler, write double *val = (double *)array_get(arr, 0) on an int array, and the compiler won’t say a word. You’ll get garbage at runtime and spend an hour wondering why. ...