Estoy usando un dsPic33F (microcontrolador de 16 bits);¿Cómo convertir una matriz de bytes a una matriz int?
- Cómo convertir
char[]
aint[]
tal que cada dos caracteres se convierte en un int usando C++? - y la operación inversa?
Estoy usando un dsPic33F (microcontrolador de 16 bits);¿Cómo convertir una matriz de bytes a una matriz int?
char[]
a int[]
tal que cada dos caracteres se convierte en un int usando C++?int* intArray = new int[sizeOfByteArray];
for (int i=0; i<sizeOfByteArray; ++i)
intArray[i] = byteArray[i];
O
std::copy(byteArray, byteArray+sizeofByteArray, intArray);
Primero debe aclarar el problema. N bytes -> N ints? si no, esto falla. La aritmética del puntero sería mejor que indexar también. –
Bueno, dijo byte [] a int [], así que asumí una correspondencia 1: 1 (de lo contrario, es solo un elenco). Sí, probablemente usaría aritmética de puntero o simplemente std :: copy, pero si alguien no sabe cómo copiar una matriz, no quiero ofuscar la operación. – Mud
¿Qué sucede si necesito obtener una int de cada 2 bytes? –
supongo que desea combinar paquetes de bytes en int?
lo que tiene que hacer es cambiar los bits al crear su int
(OKI esto es java porque yo no tengo mi código C++ aquí)
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};
}
esta lógica funciona con cualquier formato de conversión siempre y cuando conozca la longitud de sus variables
@ user440336 Entiendo tu solución. Tendría que adaptarlo a números enteros de 16 bits –
eliminar el 24, luego ^^ si obtienes la lógica, entonces puedes usar este código para convertir de cualquier formato a cualquier formato.me alegro de que ayudó –
Supongo que su matriz char contiene bytes (en lugar de caracteres ascii reales), que desea convertir en enteros de 16 bits con signo. La siguiente función funcionará para el pedido de bytes primero de MSB. Usé caracteres sin signo aquí para representar la entrada de bytes (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]);
}
}
Si necesita las definiciones de número entero, se puede usar algo como esto:
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned char uint8_t;
'i + = 2' debería ser más barato que tantos turnos de bits; –
Nota, el autor dijo acerca de ** DSP **, que en general puede tener cualquier número de bits en char (posiblemente 16), por lo que debe tener cuidado: use macro CHAR_BIT en lugar de 8, pruebe si int es suficiente para almacenar dos caracteres (2 <= sizeof (int)). – Vovanium
+1 @ Vovanium Nuevamente Dijo: "Cómo convertir char [] a int [] de modo que cada dos caracteres se convierta en un int utilizando C++" IE dos caracteres caben en un int –
En un dsPIC 33F, no creo que usted está usando C++. Si está utilizando C++, ¿qué compilador está utilizando y qué cantidad de una biblioteca de tiempo de ejecución tiene? (¿Y dónde lo obtuviste?)
Si el orden de bytes es correcto, puedes usar memcpy() si necesitas una copia, o simplemente lanzar el puntero si solo quieres usar los números de 16 bits en el buffer y la alineación está bien. Si está gestionando la memoria intermedia, no es raro utilizar una unión de este tipo de requerimientos en una plataforma como esta:
union my_buffer {
unsigned char char_buf[128];
int int_buf[64];
};
Acceso a través de char_buf cuando se trata de personajes, el acceso a través int_buf cuando se trata de enteros.
Si los bytes necesitan ser cambiados, simplemente poner en práctica una variante del hisopo() y usarlo en lugar del establecimiento de memoria(), algo así como las otras respuestas, o algún código como este:
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];
}
}
Incorrecto. Esto funcionará en su PC, pero no en dsPIC. ¡Tenga en cuenta el valor de CHAR_BIT! – Vovanium
+1 Siento que el -1 no está justificado De nuevo "Cómo convertir char [] a int [] de modo que cada dos caracteres se convierte en un int usando C++" –
@vovanium: Incorrecto. dsPIC 30/33 tiene 8 bits por byte, y también tiene CHAR_BIT definido como 8. Si CHAR_BIT no era 8, entonces ni siquiera habría un tipo int16_t. – janm
Aquí está un método compilado y probado:
#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;
}
el ByteToIntArray tarda 5 parámetros y devuelve el tamaño de la matriz convertida real, esto es muy útil si se pasa en outWordArray que es más grande que el tamaño real convertido y al mismo tiempo sirve como una forma de detectar errores.
Un simple operador de desplazamiento a bit y + se usa para combinar los dos bytes en una palabra.
Acabo de utilizar printf para probar los procedimientos y soy consciente de que para usar esto en hardware incrustado generalmente se necesita bastante espacio de código. Y acabo de incluir el intercambio de Endian para asegurarme de que pueda ver lo que debe hacer en ambos casos, pero esto puede eliminarse fácilmente en su implementación real.
También hay mucho espacio para la optimización en la rutina ByteToIntArray, pero de esta manera es fácil de entender.
Pruébelo en dsPIC antes. No hay nada en común entre los personajes de PC y dsPIC, los personajes cortos. – Vovanium
@Vovanium Él edita pregunta Usando C++ "Cómo convertir char [] a int [] tal que cada dos caracteres se convierte en int usando C++" pero bueno, así es en vivo. También ponga un -1 delante del comentario para indicar que es la razón del -1 –
En dsPIC 33 con el compilador MPLAB C30, char es de 8 bits, int es de 16 bits, y sizeof (corto) == sizeof (int) == 2. – janm
No estoy seguro de si su byte significa char u octeto. Puede tener octetos ya empaquetados por dos en las palabras de 16 bits de dsPIC, por lo que no tendrá que empaquetarlos.
#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);
}
}
Ese es un código C, pero no hay nada que tenga que ver con las funciones C++. Es compilable en el modo C++. Puede reemplazar limits.h y stddef.h con climits y cstddef para obtener una mayor conformidad con C++.
Nota sobre la aplicación:
((1<<BYTE_BIT)-1)
es una máscara de bits de N bits inferiores, donde N = BYTE_BIT. Es igual
/--N--\
...011...11 (binary)
+1 por conocer el compilador dsPIC –
(desempaquetado [1] y ((1 << CHAR_BIT) - 1)) es un tanto inútil; simplemente declararlo como (o enviar a) char sin signo para evitar la extensión del signo. – janm
@janm: si char es más ancho que los bits CHAR_BYTE, entonces esto tiene sentido. Entiendo que ESTE DSP tiene 8 bit de char, pero este no es un caso general. Razón por la que escribí esto que ya expliqué. – Vovanium
¿Quieres simplemente cambiar el tipo de cada elemento sin modificar los valores (es decir, por cada I '', 'bytearray [i] == intArray [i] ') o necesita para reinterpretar la matriz 'byte' como una matriz' int' (por ejemplo, 4 elementos 'byte' consecutivos → 1 elemento' int')? –
Supongo que quiere decir 'int' a' char'? – wilhelmtell
@In silico. Cada par de bytes se convertirá en un único int –