«Лучший» способ - не смешивать несвязанные структуры в одной функции или в одной области памяти, если на то пошло. Это просто беспорядочный дизайн.
Если вам нужно сохранить единый API для двух разных форм данных, то одной из идей может быть безопасный функционально-подобный макрос. Вы можете подделать такой макрос, чтобы иметь синтаксис, аналогичный передаче данных по указателю
void convert_hex_to_color(long hex, type* data)
, но затем используйте C11 _Generic
, чтобы фактически определить правильный тип для использования, а не использование опасных указателей на пустоту. Поскольку вы не можете передавать параметры макросам «по ссылке», вам придется прокрасться в назначении переменных. Пример:
#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;
void convert_hex_to_color(long hex, void* data);
/*
Pretty prototype just for code documentation purposes.
Never actually defined or called - the actual macro will "mock" this function.
*/
#define convert_hex_to_color(hex, output) ( *(output) = _Generic(*(output), \
rgb_t: (rgb_t){ .r=1, .g=2, .b=3 }, \
cmyk_t: (cmyk_t){ .c=1.0, .m=2.0, .y=3.0, .k=4.0 } ) )
int main(void) {
// Given
long hex = 348576;
rgb_t myrgb = { 0 };
cmyk_t mycmyk = { 0 };
convert_hex_to_color(hex, &myrgb);
convert_hex_to_color(hex, &mycmyk);
printf("RGB = %i,%i,%i\r\n", myrgb.r, myrgb.g, myrgb.b);
printf("CMYK = %f,%f,%f,%f\r\n", mycmyk.c, mycmyk.m, mycmyk.y, mycmyk.k);
return 0;
}
Вывод:
RGB = 1,2,3
CMYK = 1.000000,2.000000,3.000000,4.000000
Просто имейте в виду, что поддержка _Generic
для квалификаторов типов (const
et c) была нестабильной в C11 - одни компиляторы C11 обрабатывают const rgb_t
иначе, чем rgb_t
, другие обрабатывают их так же. Это было одно из «исправлений ошибок» в C17, поэтому используйте C17, если доступно.