Распаковщик битов Java не совпадает с C - PullRequest
1 голос
/ 22 июня 2011

Итак, мне дали программу на C, которую я пытаюсь сделать более переносимой, переводя на Java, и это шло хорошо. Тем не менее, я столкнулся с небольшим зависанием, которое, как я полагаю, лежит в этом фрагменте кода. Это просто функция, которая распаковывает 30-байтовый кадр. У меня такое чувство, что я сталкиваюсь с проблемами с типами переменных, пытаясь найти лучший способ подчинить типы Java для тех, которые не перенесены из C. Если кто-то увидит, где может быть проблема, я был бы признателен.

Java:

public static byte[] unPackBits(byte[] Src, int bitOffset, byte[] Dst, int bitCount){

    int srcByteOffset, srcBit;
    int dstByteOffset, dstBit;
    char dstMask, srcMask;

    srcByteOffset = bitOffset / 8;
    srcBit = bitOffset % 8;
    srcMask = (char)(0x01<<srcBit);

    dstByteOffset = 0;
    dstBit = 0;
    dstMask = 0x01;

    Dst[dstByteOffset] = '\0';

    for(int b = 0; b < bitCount; b++){
        if((Src[srcByteOffset] & srcMask) != (char)0x00){
            Dst[dstByteOffset] = (byte)(Dst[dstByteOffset]|dstMask);
        }
        else {
            Dst[dstByteOffset] = (byte)(Dst[dstByteOffset] & (~dstMask));
        }

        srcBit++;
        if(srcBit < 8) {
            srcMask = (char)(srcMask<<1);
        }
        else {
            srcByteOffset++;
            srcBit = 0;
            srcMask = 0x01;
        }

        dstBit++;
        if(dstBit < 8) {
            dstMask = (char)(dstMask<<1);
        }
        else {
            dstByteOffset++;
            dstMask = 0x01;
            dstBit = 0;
        }
    }
    return Dst;
}

C

void TRB::unPackBits(char *Src, int BitOffset, char *Dst, int BitCount) {
   int srcByteOffset, srcBit;
   int dstByteOffset, dstBit;
   char dstMask, srcMask;

   srcByteOffset   = BitOffset / 8;
   srcBit          = BitOffset % 8;
   srcMask = 0x01<<srcBit;

   dstByteOffset = 0;
   dstBit  = 0;
   dstMask = 0x01;
   Dst[dstByteOffset] = '\0';


   for(int b = 0; b < BitCount; b++) {
      if((Src[srcByteOffset] & srcMask) != (char)0x00) {
         Dst[dstByteOffset] = Dst[dstByteOffset] | dstMask;
      }
      else {
         Dst[dstByteOffset] = Dst[dstByteOffset] & (~dstMask);
      }

      srcBit++;
      if(srcBit < 8) {
         srcMask = srcMask<<1;
      }
      else {
         srcByteOffset++;
         srcBit = 0;
         srcMask = 0x01;
      }

      dstBit++;
      if(dstBit < 8) {
         dstMask = dstMask<<1;
      }
      else {
         dstByteOffset++;
         dstMask = 0x01;
         dstBit = 0;
      }
   }

}

Ответы [ 2 ]

1 голос
/ 23 июня 2011

Скорее всего, вы наткнулись на очень распространенную проблему с endianness . C и java могут иметь различные способы представления int в зависимости от архитектуры компьютера, на котором работает c-код.

Обычно c-программы должны преобразовывать многобайтовые целые числа в порядок сетевых байтов , чтобы упростить работу с переносимостью, аналогичную той, которую вы выполняете сейчас.

Чтобы получить правильный порядок следования байтов, вам нужно будет сдвинуть биты, используя операторы bit-shift и "and".

Также представляет интерес - пакет nio имеет функциональные возможности для простой обработки целых чисел порядка байтов LSB, обычно создаваемых устаревшим c-кодом.

0 голосов
/ 24 июня 2011

Проблема в том, что в C нет встроенного способа легкого доступа к данным внутри символа *.Функция unPackBits просто извлекает данные из определенного местоположения (BitOffset) определенной длины (BitCount) и возвращает их в той же форме.Затем эти данные должны быть преобразованы в соответствующие типы, будь то bool, int, double и т. Д.

Java, с другой стороны, имеет встроенный способ решения той же проблемы.К данным, хранящимся в байтовом массиве, можно получить доступ, используя ByteBuffer.wrap (byte []).В ByteBuffer есть функции, которые возвращают int, double, long, short, float и char, а также функции для размещения всех этих типов и несколько других полезных функций, таких как перевод всей структуры в массив int.Каждому из них нужно только указать смещение, они хранят в памяти BitCount.Единственный примитивный тип данных, который он не обрабатывает, является логическим, поэтому я все равно буду распаковывать с байтовым массивом, не проблема, поскольку я точно знаю, где в массиве хранятся эти значения.смещение, смещение всего массива перед переносом его как ByteBuffer, как предлагает @vidstige, таким же образом, как это делает первый, если еще в цикле for, и все будет в порядке.

...