2015-03-26 2 views
0

Я использую функцию (mxGetData()), которая возвращает указатель 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"); 
} 

--- UPDATE ---

После этого мне просто нужно перебрать возвращенного массива. Мне понравилась идея иметь один void *p, чтобы избежать переключения выше, но как я могу убедиться, что, когда я перебираю p, указатель перемещается на нужную сумму? Если компилятор видит p как double*, но на самом деле это «char *» (например), он выйдет за пределы диапазона.

double myCopy[nData]; 
for(i=0; i<nData; i++) 
    myCopy[i] = (double) p[i]; 
+1

Там всегда 'если (i_type == mxUINT8_CLASS) {...} еще если (...)'. –

+2

Вам не нужно вводить пустоту * (hello lundin), которая может сделать более «общее» решение возможным.Вы также можете просто назначить * все * указатели (если вам не нужны их старые значения). Для нескольких назначений, которые все еще могут быть быстрее, чем условный переход, для коммутатора. Если i_type - это перечисление с небольшими значениями, вы можете хранить массив адресов указателей void (все '* _dt', cast to' void * '), которые индексируются перечислением типа и просто присваиваются правильному. Или держите массив указателей функций на однострочные, которые выполняют назначение. –

+0

Вам нужно иметь два из этих массивов, доступных одновременно? Если нет, может также сохранить живой в общей форме и только специализировать его как-и-когда (т. Е. Внутри блока, где он используется). – Leushenko

ответ

2

А как насчет использования союза?

union { 
    void* void_dr; 
    unsigned char* uchr_dt; 
    int* int_dt; 
    // ... 
} u; 

u.void_dt = mxGetData(var); 

В зависимости от типа, вы бы затем получить доступ к u.uchr_dt и т.д.

+0

Дорога лучше, чем моя! –

+1

Он выглядит компактным, но не обеспечивает проверку того, что тип поддерживается. – AlexD

+0

@AlexD Не видя полного перечисления или остальной части кода, который фактически обрабатывает данные, трудно сказать, как можно было бы сделать это лучше всего ... –

0

Я вижу два посредственных решений. Прежде чем идти вперёд, я думаю, что оператор switch является лучшим вариантом, потому что программный сегмент может не всегда ограничиваться только назначением. Это говорит ...

Вариант № 1: Один Variable

На самом деле, это может быть разумным. Просто используйте переменную void *, чтобы захватить указатель и только запустить код, который вам нужен, убедившись, что он был выбран в этом разделе.

Другими словами, пропустите понятие здесьswitch/case и вместо того, чтобы переместить его туда, где используется значение, при условии, что вы не держась старых ценностей.

Вариант № 2: Exploit Арифметика 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 будет лучшим подходом к великой схеме вещей.

+0

Вы не можете умножить указатель на целое число! Вы можете превратить эти утверждения в тройные. – jschultz410

+0

@ jschultz410 Хорошая точка; который научит меня публиковать через часы. Крепление ... –

0

Использование char*, есть все, что наборы i_type также установить i_size, а затем использовать тетсру:

char *p = (char*) mxGetData(var); 

... 

double myCopy[nData]; 

for(i = 0; i < nData; i++) 
    memcpy(myCopy + i, p + i * i_size, i_size); 
Смежные вопросы