Convertir Bytes a Int / uint en C

4 minutos de lectura

avatar de usuario
Sam

Tengo una matriz de caracteres sin firmar[248]; lleno de bytes. Como 2F AF FF 00 EB AB CD EF ….. Esta matriz es mi flujo de bytes que almaceno mis datos del UART (RS232) como un búfer.

Ahora quiero volver a convertir los bytes en mis uint16 e int32.

En C# utilicé la clase BitConverter para hacer esto. p.ej:

byte[] Array = { 0A, AB, CD, 25 };
int myint1 = BitConverter.ToInt32(bytes, 0);
int myint2 = BitConverter.ToInt32(bytes, 4);
int myint3 = BitConverter.ToInt32(bytes, 8);
int myint4 = BitConverter.ToInt32(bytes, 12);
//...
enter code here
Console.WriteLine("int: {0}", myint1); //output Data...

¿Hay una función similar en C? (no .net, uso el compilador KEIL porque el código se ejecuta en un microcontrolador)

Saludos Sam

  • Este sitio utiliza un formato de Preguntas y Respuestas; no edite la pregunta para que contenga respuestas. Además, la respuesta que había editado en la pregunta era incorrecta de todos modos.

    –MM

    10 de noviembre de 2018 a las 22:10

avatar de usuario
carl norum

No hay una función estándar que lo haga por usted en C. Tendrá que volver a ensamblar los bytes en sus enteros de 16 y 32 bits usted mismo. ¡Cuidado con el endianismo!

Aquí hay un ejemplo simple de little-endian:

extern uint8_t *bytes;
uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);

Para un sistema big-endian, es justo el orden opuesto:

uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];

Es posible que puedas salirte con la tuya:

uint32_t myInt1 = *(uint32_t *)bytes;

Si tiene cuidado con los problemas de alineación.

  • Yo lanzaría cada uno bytes[] a un uint32_t antes de cambiarlo. Como se escribió anteriormente, se lanzarán a ints antes de hacer los turnos, pero int No es necesario que sea de 32 bits.

    – Josué Verde

    3 de septiembre de 2012 a las 3:35

  • Eso sería lo más seguro, de acuerdo.

    –Carl Norum

    3 de septiembre de 2012 a las 4:29

  • Asumiendo bytes es endian nativo, ¿con qué tipo de problemas de alineación te encontrarías? O, supongo, ¿qué tipo de situaciones hacen que la alineación sea un problema?

    – Azmísov

    24 de junio de 2015 a las 4:56

  • *(uint32_t *)bytes provoca un comportamiento indefinido (violación estricta de aliasing)

    –MM

    10 de noviembre de 2018 a las 22:11

  • ¡Gracias! ¡La mejor respuesta! ¡Salvaste mi día!

    – imike

    31 de julio de 2021 a las 11:40

avatar de usuario
Shahbaz

Sí hay. Suponga que sus bytes están en:

uint8_t bytes[N] = { /* whatever */ };

Sabemos que, un entero de 16 bits son solo dos enteros de 8 bits concatenados, es decir, uno tiene un múltiplo de 256 o, alternativamente, se desplaza por 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
             // assuming you have read your bytes little-endian

Del mismo modo para 32 bits:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
        | (uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
             // same assumption

Si los bytes se leen big-endian, por supuesto, invierte el orden:

bytes[i+1] | (uint16_t)bytes[i] << 8

y

bytes[i+3] | (uint32_t)bytes[i+2] << 8
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

Tenga en cuenta que hay una diferencia entre el endian-ness en el entero almacenado y el endian-ness de la arquitectura en ejecución. El endian-ness al que se hace referencia en esta respuesta es del entero almacenado, es decir, el contenido de bytes. Las soluciones son independientes del endian-ness de la arquitectura en ejecución, ya que el endian-ness se tiene en cuenta al cambiar.

  • luego cambia los bits menos significativos en lugar de los bits más significativos.

    – desarrollo

    02/09/2012 a las 22:40

  • @twall, creo que te refieres a bytes.

    –Carl Norum

    02/09/2012 a las 22:41

  • @sam, mira mi edición. Además, intente leer un poco sobre números binarios. Lo que estoy haciendo es una simple multiplicación.

    – Shahbaz

    02/09/2012 a las 22:43

  • pregunta tonta, pero mi Array[100] es una matriz de caracteres, pero ¿importa porque ustedes escribieron uint8_t bytes[N]

    – sam

    02/09/2012 a las 22:47

  • @sam, si char en su sistema está firmado, entonces sí, importa. Imagina 0xFF. Si viste como firmado, es -1. Entonces, en lugar de sumar 255, restarás por 1, que no es lo que querrías. unsigned char es lo mismo que uint8_t por cierto.

    – Shahbaz

    02/09/2012 a las 22:49

En el caso de little-endian, ¿no puedes simplemente usar memcpy?

memcpy((char*)&myint1, aesData.inputData[startindex], length);

avatar de usuario
andré

            char letter="A";
            size_t filter = letter;
            filter = (filter <<  8 | filter);
            filter = (filter << 16 | filter);
            filter = (filter << 32 | filter);
            printf("filter: %#I64x \n", filter); 

resultado: “filtro: 0x4141414141414141”

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad