试图避免切换
Trying to avoid a switch
我正在使用一个函数 (mxGetData()
) returns 一个指针 void*
,并且根据变量 i_type
我需要将返回的数组视为整数、浮点数、双精度数等的数组。现在我有一个很大的开关来处理每种类型,但是有什么办法可以避免这种开关吗?请注意,指针 uchr_dt
、int_dt
、flt_dt
等是不同的类型。
switch(i_type){
case mxUINT8_CLASS:
uchr_dt = (unsigned char*)mxGetData(var);
break;
case mxINT32_CLASS:
int_dt = (int*)mxGetData(var);
break;
case mxUINT32_CLASS:
uint_dt = (unsigned int*)mxGetData(var);
break;
case mxSINGLE_CLASS:
flt_dt = (float*)mxGetData(var);
break;
case mxDOUBLE_CLASS:
dbl_dt = (double*)mxGetData(var);
break;
default:
Fatal_Error("Input type not supported.\n");
}
---更新---
之后我只需要遍历返回的数组。
我喜欢用一个 void *p
来避免上面的开关的想法,但是我如何才能确保当我遍历 p
时,指针移动了正确的量?如果编译器将 p
视为 double*
,但它实际上是 'char*'(例如),它将超出范围。
double myCopy[nData];
for(i=0; i<nData; i++)
myCopy[i] = (double) p[i];
使用工会怎么样?
union {
void* void_dr;
unsigned char* uchr_dt;
int* int_dt;
// ...
} u;
u.void_dt = mxGetData(var);
根据类型,您可以访问 u.uchr_dt
等
我看到两个平庸的解决方案。在我继续之前,我认为 switch
语句是最好的选择,因为程序段可能不会 always 仅限于一个赋值。也就是说...
选项 #1: 一个变量
实际上,这可能是明智的。只需使用 void *
变量来获取指针,并且仅 运行 您需要的代码,确保将其转换为该部分。
换句话说,跳过 switch
/case
概念 这里 而是将它移动到使用该值的地方,假设你不是坚持旧价值观。
选项 #2: 利用 C 的算法
uchr_dt = (i_type == mxUINT8_CLASS) ? (unsigned char*)mxGetData(var) : NULL;
int_dt = (i_type == mxUINT16_CLASS) ? (int*)mxGetData(var) : NULL;
uint_dt = (i_type == mxUINT32_CLASS) ? (unsigned int*)mxGetData(var) : NULL;
flt_dt = (i_type == mxSINGLE_CLASS) ? (float*)mxGetData(var) : NULL;
dbl_dt = (i_type == mxDOUBLE_CLASS) ? (double*)mxGetData(var) : NULL;
有点恶心,但是序列中的所有语句除了(最多)一个会分配 NULL
而另一个会进行分配。
如果您需要保留旧值,您也可以将 NULL
替换为 (type*)xxx_dt
或其他内容。
不过就像我说的那样,即使其中一个可行,switch
声明也将是总体方案中的最佳方法。
使用char*
,设置i_type
也设置i_size
,然后使用memcpy:
char *p = (char*) mxGetData(var);
...
double myCopy[nData];
for(i = 0; i < nData; i++)
memcpy(myCopy + i, p + i * i_size, i_size);
我正在使用一个函数 (mxGetData()
) returns 一个指针 void*
,并且根据变量 i_type
我需要将返回的数组视为整数、浮点数、双精度数等的数组。现在我有一个很大的开关来处理每种类型,但是有什么办法可以避免这种开关吗?请注意,指针 uchr_dt
、int_dt
、flt_dt
等是不同的类型。
switch(i_type){
case mxUINT8_CLASS:
uchr_dt = (unsigned char*)mxGetData(var);
break;
case mxINT32_CLASS:
int_dt = (int*)mxGetData(var);
break;
case mxUINT32_CLASS:
uint_dt = (unsigned int*)mxGetData(var);
break;
case mxSINGLE_CLASS:
flt_dt = (float*)mxGetData(var);
break;
case mxDOUBLE_CLASS:
dbl_dt = (double*)mxGetData(var);
break;
default:
Fatal_Error("Input type not supported.\n");
}
---更新---
之后我只需要遍历返回的数组。
我喜欢用一个 void *p
来避免上面的开关的想法,但是我如何才能确保当我遍历 p
时,指针移动了正确的量?如果编译器将 p
视为 double*
,但它实际上是 'char*'(例如),它将超出范围。
double myCopy[nData];
for(i=0; i<nData; i++)
myCopy[i] = (double) p[i];
使用工会怎么样?
union {
void* void_dr;
unsigned char* uchr_dt;
int* int_dt;
// ...
} u;
u.void_dt = mxGetData(var);
根据类型,您可以访问 u.uchr_dt
等
我看到两个平庸的解决方案。在我继续之前,我认为 switch
语句是最好的选择,因为程序段可能不会 always 仅限于一个赋值。也就是说...
选项 #1: 一个变量
实际上,这可能是明智的。只需使用 void *
变量来获取指针,并且仅 运行 您需要的代码,确保将其转换为该部分。
换句话说,跳过 switch
/case
概念 这里 而是将它移动到使用该值的地方,假设你不是坚持旧价值观。
选项 #2: 利用 C 的算法
uchr_dt = (i_type == mxUINT8_CLASS) ? (unsigned char*)mxGetData(var) : NULL;
int_dt = (i_type == mxUINT16_CLASS) ? (int*)mxGetData(var) : NULL;
uint_dt = (i_type == mxUINT32_CLASS) ? (unsigned int*)mxGetData(var) : NULL;
flt_dt = (i_type == mxSINGLE_CLASS) ? (float*)mxGetData(var) : NULL;
dbl_dt = (i_type == mxDOUBLE_CLASS) ? (double*)mxGetData(var) : NULL;
有点恶心,但是序列中的所有语句除了(最多)一个会分配 NULL
而另一个会进行分配。
如果您需要保留旧值,您也可以将 NULL
替换为 (type*)xxx_dt
或其他内容。
不过就像我说的那样,即使其中一个可行,switch
声明也将是总体方案中的最佳方法。
使用char*
,设置i_type
也设置i_size
,然后使用memcpy:
char *p = (char*) mxGetData(var);
...
double myCopy[nData];
for(i = 0; i < nData; i++)
memcpy(myCopy + i, p + i * i_size, i_size);