Saltar al contenido

Convertir Little Endian a Big Endian

El paso a paso o código que hallarás en este artículo es la solución más sencilla y válida que encontramos a esta inquietud o dilema.

Solución:

El código de muestra de OP es incorrecto.

La conversión endian funciona a nivel de bytes de bits y de 8 bits. La mayoría de los problemas endian tienen que ver con el nivel de bytes. El código OP está haciendo un cambio endian en el nivel de nibble de 4 bits. Recomendar en su lugar:

// Swap endian (big to little) or (little to big)
uint32_t num = 9;
uint32_t b0,b1,b2,b3;
uint32_t res;

b0 = (num & 0x000000ff) << 24u;
b1 = (num & 0x0000ff00) << 8u;
b2 = (num & 0x00ff0000) >> 8u;
b3 = (num & 0xff000000) >> 24u;

res = b0 | b1 | b2 | b3;

printf("%" PRIX32 "n", res);

Si el rendimiento es realmente importante, sería necesario conocer el procesador en particular. De lo contrario, déjalo en manos del compilador.

[Edit] OP agregó un comentario que cambia las cosas.
“El valor numérico de 32 bits representado por la representación hexadecimal (st uv wx yz) se registrará en un campo de cuatro bytes como (st uv wx yz)”.

Parece que en este caso, el endian del número de 32 bits es desconocido y el resultado debe almacenarse en la memoria en pequeño orden endiano.

uint32_t num = 9;
uint8_t b[4];
b[0] = (uint8_t) (num >>  0u);
b[1] = (uint8_t) (num >>  8u);
b[2] = (uint8_t) (num >> 16u);
b[3] = (uint8_t) (num >> 24u);

[2016 Edit] Simplificación

… El tipo del resultado es el del operando izquierdo promocionado…. Operadores de desplazamiento bit a bit C11 §6.5.7 3

Usando un u después de la cambio constantes (operandos correctos) da como resultado lo mismo que sin él.

b3 = (num & 0xff000000) >> 24u;
b[3] = (uint8_t) (num >> 24u);
// same as 
b3 = (num & 0xff000000) >> 24;
b[3] = (uint8_t) (num >> 24);

Creo que puedes usar la función. htonl(). El orden de bytes de la red es big endian.

Lo siento, mi respuesta es un poco tarde, pero parece que nadie mencionó las funciones integradas para invertir el orden de los bytes, que en muy importante en términos de rendimiento.

La mayoría de los procesadores modernos son little-endian, mientras que todos los protocolos de red son big-endian. Esa es la historia y más sobre eso que puedes encontrar en Wikipedia. Pero eso significa que nuestros procesadores convierten millones de veces entre big-endian y little-endian mientras navegamos por Internet.

Es por eso que la mayoría de las arquitecturas tienen un procesador de instrucciones dedicado para facilitar esta tarea. Para arquitecturas x86 hay BSWAP instrucción, y para ARM hay REV. Esto es la forma más eficiente de invertir el orden de los bytes.

Para evitar el ensamblado en nuestro código C, podemos usar integrados en su lugar. Para GCC hay __builtin_bswap32() y para Visual C++ hay _byteswap_ulong(). Esa función generará solo una instrucción de procesador en la mayoría de las arquitecturas.

Aquí hay un ejemplo:

#include 
#include 

int main()

    uint32_t le = 0x12345678;
    uint32_t be = __builtin_bswap32(le);

    printf("Little-endian: 0x%" PRIx32 "n", le);
    printf("Big-endian:    0x%" PRIx32 "n", be);

    return 0;

Aquí está la salida que produce:

Little-endian: 0x12345678
Big-endian:    0x78563412

Y aquí está el desmontaje (sin optimización, es decir -O0):

        uint32_t be = __builtin_bswap32(le);
   0x0000000000400535 <+15>:    mov    -0x8(%rbp),%eax
   0x0000000000400538 <+18>:    bswap  %eax
   0x000000000040053a <+20>:    mov    %eax,-0x4(%rbp)

Solo hay uno BSWAP instrucción de hecho.

Entonces, si nos preocupamos por el rendimiento, deberíamos use esas funciones integradas en su lugar de cualquier otro método de inversión de bytes. Sólo mis 2 centavos.

Aquí puedes ver las comentarios y valoraciones de los usuarios

Recuerda que puedes compartir este enunciado si lograste el éxito.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *