динамическая переменная типа с пустым указателем (в конечном итоге динамическое приведение типов) в C - PullRequest
0 голосов
/ 13 июня 2018

Я только что пришел к вопросу с динамическим типом переменной (не совсем динамическим, но должен определяться во время выполнения), ситуация такова:

У меня есть функция, которая принимает преобразование двойного массиваэто в целое число и запись в файл, целое число может иметь различную битовую длину, например 8, 16 и 32. Поскольку это массив, я хочу использовать указатель для доступа к конечному результату (массиву).Поэтому я сейчас использую указатель void с помощью malloc и case case, но мне будет необходимо добавлять case каждый раз, когда я пытаюсь получить доступ к этому массиву или изменить его, мой вопрос: есть ли лучший способ сделать это?

текущий код похож на:

void foo(double * arr, int len, int iBits, FILE *fh)
{
      void * newArr;
      int iBytePerElement, iBase,i;

      iBytePerElement = iBits / 8;
      iBase = (1 << (iBits - 1)) - 1;

      switch (iBytePerElement)
      {
             case 1:
                  {
                         newArr = (int8_t *) malloc(sizeof(int8_t)*len);
                         break;
                  }
             case 2:
                  {
                         newArr = (int16_t *) malloc(sizeof(int16_t)*len);
                         break;
                  }
             case 4:
                  {
                         newArr = (int32_t *) malloc(sizeof(int32_t)*len);
                         break;
                  }
      }

      for (i = 0; i < len; ++i)
      {
              switch (iBitPerElement)
              {
                     case 1:
                          {
                                ((int8_t *)newArr)[i] = (int8_t)(arr[i]*iBase);
                                 break;
                          }
                     case 2:
                          {
                                ((int16_t *)newArr)[i] = (int16_t)(arr[i]*iBase);
                                 break;
                          }
                     case 4:
                          {
                                ((int32_t *)newArr)[i] = (int32_t)(arr[i]*iBase);
                                 break;
                          }
              }
      }
      fwrite(newArr, iBytePerElement, iBytePerElement*len,fh);
}

1 Ответ

0 голосов
/ 13 июня 2018

Делая несколько предположений о том, что вы, вероятно, имели в виду, когда ваш пример кода не определен (прокомментирован), вот как я мог бы это сделать:

#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
void *foo(double * arr, int len, int iBits)  //should return the malloced array not void
{
      void * newArr;
      int iBytePerElement, iBase, i;

      iBytePerElement = iBits / 8;
      iBase = (1 << (iBits - 1)) - 1;

      if(NULL==(newArr = malloc(iBits/CHAR_BIT))) return NULL; //replace the first switch
      //which obviously meant to alloc sizeof(int16_t)*len in the case 2 branch (not (sizeof(int8_t)*len) etc

      for (i = 0; i < len; ++i) {
          switch(iBytePerElement){
          break; case 1: ((int8_t *)newArr)[i] = arr[i]*iBase; 
          break; case 2: ((int16_t *)newArr)[i] = arr[i]*iBase;
          break; case 4: ((int32_t *)newArr)[i] = arr[i]*iBase;
          }
      }
      return newArr;
}

По сути, вам нужен только второй переключатель.

Если вы хотите избавиться от второго переключателя, вы можете заменить его на функцию воспроизведения указателя.Например:

#include <stdint.h>
#include <stdlib.h>
#include <limits.h>

#define MK_FN(Bits) \
void to##Bits(void *newArr, double const*arr, int len) \
{ \
    int i; for(i=0; i < len; i++) ((int##Bits##_t *)newArr)[i] = arr[i]*((1<<(Bits-1)-1));  \
} 
MK_FN(8)
MK_FN(16)
MK_FN(32)



void *foo(double * arr, int len, int iBits)  //should return the malloced array not void
{
      void * newArr;
      int iBytePerElement = iBits / 8;

      if(NULL==(newArr = malloc(iBits/CHAR_BIT))) return NULL;
      ((void (*[])(void *,double const*, int)){ [1]=to8, [2]=to16, [4]=to32, })[iBits](newArr,arr,len);
      return newArr;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...