Как преобразовать байтовый массив в массив int? - PullRequest
5 голосов
/ 12 ноября 2010

Я использую dsPic33F (16-битный микроконтроллер);

  • Как преобразовать char[] в int[] так, чтобы каждые два символа превращались в int с использованием C ++?
  • а обратная операция?

Ответы [ 6 ]

3 голосов
/ 12 ноября 2010
int* intArray = new int[sizeOfByteArray];

for (int i=0; i<sizeOfByteArray; ++i)
   intArray[i] = byteArray[i];

Или

std::copy(byteArray, byteArray+sizeofByteArray, intArray);
1 голос
/ 12 ноября 2010

Полагаю, вы хотите объединить пакеты байтов в int?

Что вам нужно сделать, это сдвинуть биты, когда вы создаете свой int

(Оки, это Java, потому что я нездесь нет моего кода C ++)

public static final int byteArrayToInt(byte [] b) {
    return (b[0] << 24)
            + ((b[1] & 0xFF) << 16)
            + ((b[2] & 0xFF) << 8)
            + (b[3] & 0xFF);
}

public static final byte[] intToByteArray(int value) {
    return new byte[] {
            (byte)(value >>> 24),
            (byte)(value >>> 16),
            (byte)(value >>> 8),
            (byte)value};
}

эта логика работает с любыми форматами преобразования, если вы знаете длину ваших переменных

0 голосов
/ 12 ноября 2010

Я не уверен, что твой байт означает символ или октет. Возможно, у вас уже есть октеты, упакованные по два в 16-битных словах dsPIC, поэтому вам больше не нужно их упаковывать.

#include <limits.h>
#include <stddef.h>

#define BYTE_BIT CHAR_BIT /* Number of significant bits in your 'byte' * Read note below */

/* pack routine */
void ipackc(int *packed, const char *unpacked, size_t nints) {
    for(; nints>0; nints--, packed++, unpacked += 2) {
        *packed = (unpacked[0]<<BYTE_BIT) | (unpacked[1] & ((1<<BYTE_BIT)-1));
    }
}

/* unpack routine */
void cunpacki(char *unpacked, const int *packed, size_t nints) {
    for(; nints>0; nints--, packed++, unpacked += 2) {
        unpacked[0] = *packed>>BYTE_BIT;
        unpacked[1] = *packed & ((1<<BYTE_BIT)-1);
    }
}

Это код на C, но нет ничего общего с функциями C ++. Компилируется в режиме C ++. Вы можете заменить limit.h и stddef.h на climits и cstddef для более строгого соответствия C ++.

  • Примечание: этот код не будет работать, если 2 ваших «байта» не могут поместиться в int. Проверь это. Число битов в int должно быть не менее 2 * BYTE_BIT или один из символов будет потерян. Если вы имеете в виду 8-битный октет под 'байтом', вы можете изменить CHAR_BIT в определении BYTE_BIT на 8, и тогда 16-битный int будет правильно соответствовать октетам.

Примечание о реализации:

((1<<BYTE_BIT)-1)

- битовая маска для N младших битов, где N = BYTE_BIT. Это равно

    /--N--\
...011...11 (binary)
0 голосов
/ 12 ноября 2010

Вот скомпилированный и протестированный метод:

#include <stdio.h>

unsigned short ByteToIntArray( 
        unsigned char inByteArray[], 
        unsigned short inArraySize, 
        unsigned short outWordArray[], 
        unsigned short outArraySize, 
        unsigned char swapEndian
    )
{
    if (    ( inArraySize/2 > outArraySize )
         || ( outArraySize == 0 ) 
         || ( inArraySize == 0 )
       )
    {
        return -1;        
    }

    unsigned short i;

    if ( swapEndian == 0 )
    {    
        for ( i = 0; i < outArraySize; ++i )
        {
            outWordArray[ i ] = ( (unsigned short)inByteArray[ i*2 ] << 8 ) + inByteArray[ i*2 + 1 ];
        }
    }
    else
    {
        for ( i = 0; i < outArraySize; ++i )
        {
            outWordArray[ i ] = ( (unsigned short)inByteArray[ i*2 + 1 ] << 8 ) + inByteArray[ i*2 ];
        }
    }
    return i;    
}


int main(){
    unsigned char ucArray[ 16 ] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
    unsigned short usArray[ 8 ];
    unsigned short size;

     // "/ 2" on the usArray because the sizes are the same in memory
     size = ByteToIntArray( ucArray, sizeof( ucArray ), usArray, sizeof( usArray ) / 2, 0 );

    if( size > 0 )
    {
        printf( "Without Endian Swapping:\n" );
        for( unsigned char i = 0; i < size ; ++i )
        {
            printf( "0x%04X ", usArray[ i ] );
        }
        printf( "\n" );
    }

    if( size > 0 )
    {
         // "/ 2" on the usArray because the sizes are the same in memory
        size = ByteToIntArray( ucArray, sizeof( ucArray ), usArray, sizeof( usArray ) / 2, 1 );

        printf( "With Endian Swapping:\n" );
        for( unsigned char i = 0; i < size ; ++i )
        {
            printf( "0x%04X ", usArray[ i ] );
        }
        printf( "\n" );
    }
    return 0;
}

ByteToIntArray принимает 5 параметров и возвращает размер фактического преобразованного массива, это удобно, если вы передадите outWordArray , который больше, чем фактический преобразованный размер, и в то же время служит способом выявления ошибок.

Простой оператор побитового сдвига и + используется для объединения двух байтов водно слово.

Я просто использовал printf для тестирования процедур, и я знаю, что для использования этого во встроенном оборудовании обычно требуется много места для кода.И я просто включил обмен Endian, чтобы убедиться, что вы можете видеть, что вам нужно сделать в обоих случаях, но это может быть легко удалено в вашей реальной реализации.

В также есть много возможностей для оптимизации.ByteToIntArray рутина, но это легко понять.

0 голосов
/ 12 ноября 2010

В dsPIC 33F я сомневаюсь, что вы используете C ++.Если вы используете C ++, какой компилятор вы используете, и сколько у вас библиотек времени выполнения?(И где вы это взяли!)

Если порядок байтов правильный, вы можете просто использовать memcpy (), если вам нужна копия, или просто привести указатель, если вы просто хотите использовать 16-битные числав буфере и выравнивание в порядке.Если вы управляете буфером, нет ничего необычного в том, чтобы использовать объединение для такого типа требований на такой платформе:

union my_buffer {
    unsigned char char_buf[128];
    int int_buf[64];
};

Доступ через char_buf при работе с символами, доступ через int_buf при работе с int.

Если нужно поменять местами байты, просто реализуйте вариант swab () и используйте его вместо memcpy (), что-то вроде других ответов или некоторый код, подобный этому:

void doit(int16_t* dest, char const* src, size_t word_count)
{
    char* const end = (char*) (dest + word_count);
    char* p;

    for (p = (char*) dest; p != end; src += 2, p += 2) {
        p[0] = src[1];
        p[1] = src[0];
    }
}
0 голосов
/ 12 ноября 2010

Я предполагаю, что ваш массив символов содержит байты (вместо реальных символов ASCII), которые вы хотите преобразовать в 16-разрядные целые числа со знаком.Приведенная ниже функция будет работать для упорядочения байтов в MSB.Я использовал здесь символы без знака для представления байтового ввода (uint8_t).

void BytesToInts(uint8_t *byteArray, uint16_t byteArraySize, int16_t *intArray, uint16_t intArraySize) {</p> <pre><code> //do some error checking on the input if (byteArraySize == 0) return; if (intArraySize != (byteArraySize/2)) return; //convert each pair of MSB-first bytes into a signed 16-bit integer for (uint16_t i=0; i<intArraySize; i++) { intArray[i] = (int16_t) ((byteArray[i<<1]<<8) | byteArray[(i<<1)+1]); }

}

Если вам нужны целочисленные определения, вы можете использовать что-то вроде этого:


typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned char uint8_t;

...