Extraer bytes en tiempo de compilación con comprobación de tipos

Bartomeu es un chavalote que suele andar por algunos foros y news, tanto respondiendo a la gente como haciendo él mismo preguntas, y el otro día presentó una idea bastante buena en el grupo de desarrollo de las news de Lechado.

Muchas veces nos encontramos con el problema de extraer un byte de una variable más larga para realizar diferentes operaciones con él, y muchas veces también nos liamos un poco con tanto hexadecimal y operador lógico… pero dejemos que sea él mismo quien nos lo explique:

El otro día tuve un momento de inspiración y, buscando otra cosa, inventé una nueva solución para un problema clásico que no necesitaba solucionar en ese momento.

El problema es cómo conseguir sólo el segundo byte de una variable long. (El problema es análogo para conseguir cualquier otro byte). Hay tres soluciones clásicas, (suponiendo que L es el long):

1º solución: La matemática. En tiempo de ejecución

char B1 = (L/256)%256; // falla si L<0

2º solución: La lógica. En tiempo de ejecución

char B2 = (L&0xff00)>>8;

3º solución: Con union. En tiempo de compilación

union {
    long L;
    char B[4];
} U;

U.L = L;
char B3 = U.B[1];

Obliga a crear una union y a grabar los datos por un campo y leerlos por otro

4ª solución: ¡¡Nueva!! En tiempo de compilación

char B4 = reinterpret_cast<char *>(&L)[1];

A primera vista puede intimidar. Pero el codigo generado por el compilador es exactamente el mismo que se genera en la instrucción "B3=U.B[1]" y te ahorras tener que definir ninguna union ni tienes que usar la instrucción previa "U.L = L".

Tiene la ventaja añadida que sirve para cualquier tipo de L. Con esa instrucción obtienes el segundo byte de cualquier cosa.

Además, por si fuera poco, tambien sirve como operador a la izquierda;

reinterpret_cast<char *>(&L)[1] = 0;

Ahora el segundo byte de L es cero, los otros bytes siguen igual.

Este uso del reinterpret_cast no lo he visto en ningún otro sitio y no se si he tenido una buena idea o tiene algún inconveniente que no se ver.

3 comentarios en “Extraer bytes en tiempo de compilación con comprobación de tipos”

  1. Rafa,

    La verdad es que la técnica no es ninguna novedad, es el “truco sucio” de C usado desde los ’70 para interpretar la dirección de una variable como dirección de inicio de un array de bytes, para luego acceder a cualquiera de ellos mediante []…

    Solo que ahora en el C++ moderno se usa reinterpret_cast para hacer el uso del “truco” más claro.

    Abrazo – Octavio

  2. ¡Ocatvio! ¡Cuánto tiempo sin saber de ti! ¿Qué tal?

    Claro, eso se hace bastante a menudo en el desarrollo de hardware cuando tienes que acceder directamente al hard, pero “a la C”. Yo suelo hacerlo, aunque siempre intento que sólo ocurra en la parte de más bajo nivel, aunque a veces no es posible…

    De todos modos, con reinterpret_cast es la primera vez que lo veo…

Deja un comentario

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