I'm trying to build a generic function that can populate a struct without any dynamic memory allocation.
The following code is a naive example of what I'm trying to do.
This code will not compile as incomplete type 'void' is not assignable
.
Please note that this is a toy example to highlight my problems. I don't really want to convert colours; I just want to highlight that the structures will be different in data types and size.
#include <stdio.h>
typedef struct {
int r;
int g;
int b;
} rgb_t;
typedef struct {
float c;
float m;
float y;
float k;
} cmyk_t;
typedef enum { RGB, CMYK } color_t;
void convert_hex_to_color(long hex, color_t colorType, void* const out) {
if (colorType == RGB) {
rgb_t temp = { 0 };
// Insert some conversion math here....
temp.r = 1;
temp.g = 2;
temp.b = 3;
*out = temp; //< [!]
} else
if (colorType == CMYK) {
cmyk_t temp = { 0 };
// Insert some conversion math here....
temp.c = 1.0;
temp.m = 2.0;
temp.y = 3.0;
temp.k = 4.0;
*out = temp; //< [!]
}
}
int main(void) {
// Given
long hex = 348576;
rgb_t mydata = { 0 };
convert_hex_to_color(hex, RGB, (void*)(&mydata));
// Then
printf("RGB = %i,%i,%i\r\n", mydata.r, mydata.g, mydata.b);
return 0;
}
For some additional context, I'm using C11 on an embedded system target.
What is the best[1] way to do this? Macro? Union?
Regards,
Gabriel
[1] I would define "best" as a good compromise between readability and safety.
The reason for the error is it is invalid to store via a void
pointer: the compiler does not know what to store. You could cast the pointer as *(rgb_t *)out = temp;
or *(cmyk_t *)out = temp;
Alternately, you could define temp
as a pointer to the appropriate structure type and initialize it directly from out
, without the cast that is not needed in C:
void convert_hex_to_color(long hex, color_t colorType, void *out) {
if (colorType == RGB) {
rgb_t *temp = out;
// Insert some conversion math here....
temp->r = 1;
temp->g = 2;
temp->b = 3;
} else
if (colorType == CMYK) {
cmyk_t *temp = out;
// Insert some conversion math here....
temp->c = 1.0;
temp->m = 2.0;
temp->y = 3.0;
temp->k = 4.0;
}
}
Note that the cast is not needed in C:
int main(void) {
// Given
long hex = 348576;
rgb_t mydata = { 0 };
convert_hex_to_color(hex, RGB, &mydata);
// Then
printf("RGB = %i,%i,%i\r\n", mydata.r, mydata.g, mydata.b);
return 0;
}