2010-11-12 1 views
5

Я использую dsPic33F (16-разрядный микроконтроллер);Как преобразовать массив байтов в массив int?

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

Вы хотите просто изменить тип каждого элемента без изменения значения (то есть, для каждого '' i', ByteArray, [I] == INTArray [я] ') или вам нужно переинтерпретировать массив 'byte' как массив' int' (например, 4 последовательных элемента 'byte' → 1' int' element)? –

+0

Я полагаю, вы имеете в виду 'int' to' char'? – wilhelmtell

+0

@ В силиконе. Каждая пара байтов будет преобразована в один int –

ответ

3
int* intArray = new int[sizeOfByteArray]; 

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

Или

std::copy(byteArray, byteArray+sizeofByteArray, intArray); 
+0

Сначала вам необходимо прояснить проблему. N байтов -> N ints? если это не так. Арифметика указателя была бы лучше индексации. –

+0

Ну, он сказал байт [] в int [], поэтому я принял соответствие 1: 1 (иначе это просто литье). Да, я бы, вероятно, использовал арифметику указателей или просто std :: copy, но если кто-то не знает, как скопировать массив, я не хочу обфускации операции. – Mud

+1

Что делать, если мне нужно получить int каждые 2 байта? –

1

Я предполагаю, что вы хотите, чтобы объединить пакеты байтов в междунар?

то, что вам нужно сделать, это сдвинуть биты при создании ИНТ

(оки это 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

@ user440336 Я понимаю ваше решение. Мне пришлось бы адаптировать его к 16-битным целым числам –

+0

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

0

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

void BytesToInts(uint8_t *byteArray, uint16_t byteArraySize, int16_t *intArray, uint16_t intArraySize) {

//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; 
 
+0

'i + = 2' должен быть дешевле, чем так много бит сдвигов; –

+0

Обратите внимание, что автор сказал о ** DSP **, который, как правило, может содержать любое количество бит в char (возможно, 16), поэтому вы должны быть осторожны: используйте макрос CHAR_BIT вместо 8, проверьте, достаточно ли int для хранения двух символов (2 <= SizeOf (INT)). – Vovanium

+0

+1 @ Vovanium Again Он сказал: «Как преобразовать char [] в int [], чтобы каждый два символа стал int с использованием C++« IE два символа будут вписываться в int –

0

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

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

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

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

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

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

Неправильно. Это будет работать на вашем ПК, но не будет на dsPIC. Помните о значении CHAR_BIT! – Vovanium

+0

+1 Я чувствую, что -1 необоснованно Снова «Как преобразовать char [] в int [], чтобы каждый два символа стал int с использованием C++« –

+1

@vovanium: Wrong. dsPIC 30/33 имеет 8 бит на байт, и поэтому CHAR_BIT определяется как 8. Если CHAR_BIT не был 8, тогда даже не было типа int16_t. – janm

-1

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

#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

Протестируйте его на dsPIC раньше. Нет ничего общего между символами ПК и dsPIC, шортами ant ints. – Vovanium

+0

@Vovanium Он редактирует запрос Используя C++ «Как преобразовать char [] в int [], чтобы каждый два символа стал int с использованием C++», но эй так жив. Также помещается -1 перед комментарием, чтобы указать, что это причина для -1 –

+3

На dsPIC 33 с компилятором MPLAB C30, char имеет 8 бит, int - 16 бит, а sizeof (short) == sizeof (int) == 2. – janm

0

Я не уверен, что ваш байтовый символ или октет. У вас могут быть октеты, уже упакованные по два в 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++. Вы можете заменить limits.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

+1 за знание компилятора dsPIC –

+0

(распакованный [1] и ((1 << CHAR_BIT) - 1)) все немного бессмысленно; просто объявите его как (или отбрасывайте) неподписанным символом, чтобы избежать расширения знака. – janm

+0

@janm: Если char шире бит CHAR_BYTE, тогда это имеет смысл. Я понимаю, что этот DSP имеет 8-битный символ, но это не общий случай. Причина, которую я написал, я уже объяснил. – Vovanium