2011-09-01 16 views
12

Sono interessato a scrivere una funzione getMyByteChunkFunction che accetta due parametri: un numero intero a 32 bit e un offset di byte (0, 1, 2 o 3), quindi restituisce il byte corrispondente del numero intero a 32 bit. Ad esempio, in questo intero:Operatore bit a bit per ottenere byte da 32 bit

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

la chiamata di funzione getMeByteChunkFunction(word, 2) rendimenti 00001001.

Tuttavia, sono limitato agli operatori bit a bit che è possibile utilizzare. Sono autorizzato a utilizzare >>, << e esattamente una sottrazione. So come farlo usando AND e XOR, ma non so come utilizzerei una sottrazione qui. Qualche idea?

+0

Etichettato come compiti a casa (dovuto cadere "logica" perché max 5 tag.) –

+0

@JBentley: ho fatto quel commento di due anni fa. –

risposta

6

È possibile farlo solo con lo spostamento. Spostati a sinistra per eliminare i bit a sinistra, quindi sposta a destra per eliminare i bit a destra e sposta il byte desiderato nel punto meno significativo.

+0

Non ha problemi se il bithift è in grado di conservare i segnali? – templatetypedef

+2

Sei autorizzato a trasmettere prima a unsigned? Questo si prenderà cura di esso. In caso contrario, vai con la risposta di templatetypedef. –

25

Un'idea è la seguente. Si supponga di avere un valore quattro byte come questo:

aaaaaaaa bbbbbbbb cccccccc dddddddd 

Supponiamo che si desidera ottenere il byte bbbbbbbb fuori da questo. Se si sposta a destra da due byte, si ottiene

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

Questo valore è uguale a ciò che si vuole, tranne che nella parte superiore ha ???????? ???????? aaaaaaaa (perché non siamo sicuri se il turno è segno-conservazione o no , dal momento che non so se il tuo valore non è firmato o no.) Nessuna preoccupazione, però; possiamo sbarazzarci di questi valori sconosciuti e del byte a. Per sbarazzarsi della parte superiore, si supponga che si sposta a destra un altro byte, dando

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

Ora, spostamento a sinistra un byte per ottenere

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

Se poi si esegue questa sottrazione, si ottiene

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

E voilà ... hai il valore che desideri!

Lascerò il codice effettivo come esercizio al lettore. Non preoccuparti; non è particolarmente difficile. :-)

+0

Sembra che la sinistra e la destra siano mescolate? –

+0

@Tom Zych- Whoops! Grazie per averlo capito. Sono pessimo nel dare indicazioni. :-) – templatetypedef

+0

@templatetypedef, commento errato in post ... mi riposo meglio per un po '. ;-). –

0

ecco il codice:

#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; 
} 

e l'uscita:

aa09ca05 
09 
+0

Non funzionerà sulla maggior parte dei compilatori se si utilizza solo un lungo però .. – Voo

+0

specifica ANSI/ISO C dice che a lungo mi deve almeno 4 byte. Conosci qualche compilatore C ANSI compatibile su cui non funzionerà? –

+3

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

1

C'è un trucco molto intelligente per questo, che io uso per la conversione di oggetti in stringhe char (per trasmettere come flusso):

//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 

In breve, la sorgente sopra tratta come 4 caratteri separati (che normalmente onl y 1 byte in size), e il puntatore consente di trattarlo come una sezione di memoria. Tu lo chiami prima di tornare.

Utilizzarlo a qualsiasi scopo (anche commerciale).

Formato compresso?

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

Il seguente codice deve anche rispondere alla domanda.

#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; 
} 

L'uscita è

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

Il concetto può essere spiegato sulla base templatetypedef s' spiegazione e ampliato come segue.

(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

Spiegazione, per favore? –