2011-09-01 9 views
12

Estoy interesado en escribir una función getMyByteChunkFunction que acepta dos parámetros: un entero de 32 bits y un desplazamiento de bytes (0, 1, 2 o 3), luego devuelve el byte correspondiente del entero de 32 bits. Por ejemplo, dado este entero:Operador bit a bit para obtener bytes de 32 bits

  (3)   (2)  (1)  (0) ---byte numbers 
int word = 10101010 00001001 11001010 00000101 

la llamada de función getMeByteChunkFunction(word, 2) rendimientos 00001001.

Sin embargo, estoy limitado en los operadores de bit a bit que puedo usar. Solo puedo usar >>, << y exactamente una resta. Sé cómo hacer esto usando AND y XOR, pero no sé cómo usaría una resta aquí. ¿Algunas ideas?

+0

Etiquetado como tarea (tuvieron que abandonar la "lógica" porque un máximo de 5 etiquetas.) –

+0

@JBentley: Hice ese comentario hace dos años. –

Respuesta

6

Puede hacerlo solo con el cambio. Gire a la izquierda para deshacerse de los bits de la izquierda, luego desplace hacia la derecha para deshacerse de los bits de la derecha y mueva el byte deseado al punto menos significativo.

+0

¿Esto no tiene problemas si el cambio de bits preserva los signos? – templatetypedef

+2

¿Se le permite lanzarlo primero sin firma? Eso se encargará de eso. Si no, ve con la respuesta de templatetypedef. –

25

Una idea es la siguiente. Supongamos que tiene un valor de cuatro bytes como éste:

aaaaaaaa bbbbbbbb cccccccc dddddddd 

Supongamos que usted quiere conseguir el byte bbbbbbbb salir de esto. Si se desplaza a la derecha por dos bytes, se obtiene

???????? ???????? aaaaaaaa bbbbbbbb 

Este valor es igual a lo que quiere, excepto que en la parte superior que tiene ???????? ???????? aaaaaaaa (porque no estamos seguros de si el cambio es signo de preservación o no , ya que no sé si su valor no está firmado o no). Sin embargo, sin preocupaciones; podemos deshacernos de estos valores desconocidos y el byte a. Para deshacerse de la parte superior, supongamos que se desplaza a la derecha otro byte, dando

???????? ???????? ???????? aaaaaaaa 

Ahora, desviación a la izquierda de un byte para obtener

???????? ???????? aaaaaaaa 00000000 

Si a continuación hace esto resta, se obtiene

???????? ???????? aaaaaaaa bbbbbbbb 
- ???????? ???????? aaaaaaaa 00000000 
--------------------------------------- 
    00000000 00000000 00000000 bbbbbbbb 

Y voil & agrave; ... ¡tiene el valor que desea!

Voy a dejar el código real como un ejercicio para el lector. No te preocupes no es particularmente difícil. :-)

+0

Parece que tiene su izquierda y derecha mezclada? –

+0

@Tom Zych- ¡Vaya! Gracias por atrapar eso. Soy pésimo en dar indicaciones. :-) – templatetypedef

+0

@templatetypedef, comentario incorrecto en la publicación ... Mejor descanso por un tiempo. ;-). –

0

aquí está el código:

#include <stdio.h> 

int main() { 
    unsigned long n = 0xAA09CA05L; /* 10101010 00001001 11001010 00000101 */ 
    printf("%08lx\n", n); /* input */ 
    printf("%02lx\n", ((n<<8)>>24)); /* output */ 
    return 0; 
} 

y la salida:

aa09ca05 
09 
+0

No funcionará en la mayoría de los compiladores si solo usa un largo aunque ... – Voo

+0

La especificación ANSI/ISO C dice que me debe al menos 4 bytes. ¿Conoces algún compilador de C compatible con ANSI en el que no funcione? –

+3

http://meta.stackexchange.com/questions/10811/how-to-ask-and-answer-homework-questions –

1

Hay un truco muy inteligente para esto, que utilizo para convertir objetos en cadenas char (para transmitir como una corriente):

//WhichByte should really be an enum to avoid issues 
//Counts as 0, 1, 2 or 3 
//Modify as unsigned or signed char (for return type and pointer type) as needed 
#define BYTE_TYPE unsigned char 
BYTE_TYPE GetByte(const unsigned int Source, const unsigned char WhichByte) 
{ 
    if(WhichByte < 0){return 0;} 
    if(WhichByte >= sizeof(Source)){return 0;} 

    //Converts source into the appropriate pointer 
    BYTE_TYPE * C_Ptr = (BYTE_TYPE *)&Source; 
    return *(C_Ptr+WhichByte); 
} 
#undef BYTE_TYPE 

En resumen, la fuente trata anteriormente como 4 caracteres separados (que son normalmente ONL y 1 byte de tamaño), y el puntero le permite tratarlo como una sección de memoria. Lo desreferencia antes de regresar.

Úselo para cualquier propósito (incluso comercial).

¿Formato comprimido?

#define GetByte(X,Y) (*(((unsigned char *)&X)+Y)) 
2

El siguiente código también debe responder la pregunta.

#include <stdio.h> 

int getByte(int x, int n); 

void main() 
{ 
    int x = 0xAABBCCDD; 
    int n; 

    for (n=0; n<=3; n++) { 
     printf("byte %d of 0x%X is 0x%X\n",n,x,getByte(x,n)); 
    } 

} 

// extract byte n from word x 
// bytes numbered from 0 (LSByte) to 3 (MSByte) 
int getByte(int x, int n) 
{ 
    return (x >> (n << 3)) & 0xFF; 
} 

La salida es

byte 0 of 0xAABBCCDD is 0xDD 
byte 1 of 0xAABBCCDD is 0xCC 
byte 2 of 0xAABBCCDD is 0xBB 
byte 3 of 0xAABBCCDD is 0xAA 

El concepto se puede explicar en base a templatetypedef 's explicación y se expandió como sigue.

(3)  (2)  (1)  (0) 
aaaaaaaa bbbbbbbb cccccccc dddddddd 

{(3),(2),(1),(0)} --> {(3)} 
    ???????? ???????? ???????? aaaaaaaa // x>>(3*8) where 3 == n 
& 00000000 00000000 00000000 11111111 // 0xFF 
    ----------------------------------- 
    00000000 00000000 00000000 aaaaaaaa // (x >> (8 * n)) & 0xFF 

{(3),(2),(1),(0)} --> {(2)} 
    ???????? ???????? aaaaaaaa bbbbbbbb // x>>(2*8) where 2 == n 
& 00000000 00000000 00000000 11111111 // 0xFF 
    ----------------------------------- 
    00000000 00000000 00000000 bbbbbbbb 

{(3),(2),(1),(0)} --> {(1)} 
    ???????? aaaaaaaa bbbbbbbb cccccccc // x>>(1*8) where 1 == n 
& 00000000 00000000 00000000 11111111 // 0xFF 
    ----------------------------------- 
    00000000 00000000 00000000 cccccccc 

{(3),(2),(1),(0)} --> {(0)} 
    aaaaaaaa bbbbbbbb cccccccc dddddddd // x>>(0*8) where 0 == n 
& 00000000 00000000 00000000 11111111 // 0xFF 
    ----------------------------------- 
    00000000 00000000 00000000 dddddddd 

Note (x >> (8 * n)) & 0xFF is equivalent to (x >> (n << 3)) & 0xFF. 

64 32 16 8 4 2 1 
---------------- 
0 0 0 0 0 1 1 // (n==3) 
0 0 1 1 0 0 0 // (n*8==n<<3==24) 
---------------- 
0 0 0 0 0 1 0 // (n==2) 
0 0 1 0 0 0 0 // (n*8==n<<3==16) 
---------------- 
0 0 0 0 0 0 1 // (n==1) 
0 0 0 1 0 0 0 // (n*8==n<<3==8) 
---------------- 
2
result = (word >> (n_byte << 3)) & 0xFF; 
+0

Explicación, por favor? –