我正在C中编写一个用于低级别图像处理的基本库。我知道还有其他(非常好的)库;这对我来说是一次学习经历,而不是达到目的的手段。
我定义了以下(对于这个问题,简化了)结构:
union img_rawdata{
uint8_t* u8;
uint16_t* u16;
float* flt;
};
enum img_type{
IMG_U8,
IMG_U16,
IMG_FLT
};
struct image{
union img_rawdata rawdata;
enum img_type type;
unsigned int num_values;
};
我的问题是:在联合中动态分配正确指针的最受欢迎的方式是什么?
现在,我看到的唯一方法是使用switch语句,比如:
void alloc_img(struct image* img, enum img_type type, unsigned int num_vals){
switch (type){
case IMG_U8:
img->rawdata.u8 = (uint8_t*)malloc(num_vals*sizeof(uint8_t));
break;
case IMG_U16:
img->rawdata.u16 = (uint16_t*)malloc(num_vals*sizeof(uint16_t));
break;
case IMG_FLT:
img->rawdata.flt = (float*)malloc(num_vals*sizeof(float));
break;
}
}
这似乎没那么糟糕;然而,在我的实现中,实际的内存分配大约是50行(因为rawdata不是一维的,错误检查等)
有没有什么预处理器的魔力可以减少代码冗余,或者这是写这篇文章的最佳方式?
或者,有没有一种完全不同的方法来处理这个问题,从而完全避免这个问题?
[假设包括void *
在内的所有类型的指针都具有相同的大小]
修改你喜欢的东西,这样
union img_rawdata {
void * untyped;
uint8_t * u8;
uint16_t * u16;
float * flt;
};
enum img_type {
IMG_UNDEF = -1
IMG_U8 = 0,
IMG_U16,
IMG_FLT,
IMG_MAX
};
并添加
const size_t img_type_size[IMG_MAX] = {
sizeof(*((union img_rawdata *) NULL)->u8),
sizeof(*((union img_rawdata *) NULL)->u16),
sizeof(*((union img_rawdata *) NULL)->flt)
};
然后将开关替换为:
assert(IMG_UNDEF < type && IMG_MAX > type);
img->rawdata.untyped = malloc(num_vals * img_type_size[type]);
void alloc_img(struct image * img, enum img_type type, unsigned int num_vals){
size_t basesize = 0;
switch (type){
case IMG_U8:
basesize = sizeof(uint8_t);
break;
case IMG_U16:
basesize = sizeof(uint16_t);
break;
case IMG_FLT:
basesize = sizeof(float);
break;
}
if (basesize) {
img->rawdata.u8 = malloc(num_vals * basesize);
// assigning to u8 is the same as assigning to any other member
// but it may be better to use a void* as in
// img->rawdata.voidptr = malloc(num_vals * basesize);
} else {
fprintf(stderr, "default missing in switchn");
}
}