我正在为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不是一维的,错误检查等)。
是否有任何可以减少代码冗余的预处理器魔法,或者这是编写此代码的最佳方式?
或者,或者,是否有完全不同的方式来解决问题,完全避免这个问题?
答案 0 :(得分:6)
[假设所有类型的指针包括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]);
答案 1 :(得分:3)
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 switch\n");
}
}