2011-09-01 13 views
12

Interesuje mnie napisanie funkcji getMyByteChunkFunction, która akceptuje dwa parametry - 32-bitową liczbę całkowitą i przesunięcie bajtowe (0, 1, 2 lub 3), a następnie zwraca odpowiedni bajt na zewnątrz 32-bitowej liczby całkowitej. Na przykład, biorąc pod uwagę to całkowita:Bitowy operator, aby uzyskać bajt z 32 bitów

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

wywołanie funkcji getMeByteChunkFunction(word, 2) powraca 00001001.

Jednak jestem ograniczony w operatory bitowe mogę używać. Mogę używać tylko >>, << i dokładnie odejmowania. Wiem, jak to zrobić za pomocą AND i XOR, ale nie wiem, jak bym użył odejmowania tutaj. Jakieś pomysły?

+0

oznaczone jako praca domowa (musiał upuścić "logikę", bo max 5 tagów). –

+0

@JBentley: Zrobiłem ten komentarz dwa lata temu. –

Odpowiedz

6

Możesz to zrobić po prostu przesuwając. Przesuń w lewo, aby pozbyć się bitów po lewej stronie, a następnie przesuń w prawo, aby pozbyć się bitów po prawej stronie i przenieś wybrany bajt w najmniej znaczące miejsce.

+0

Czy to nie ma problemu, jeśli zmiana znaku polega na zachowaniu znaku? – templatetypedef

+2

Czy można go najpierw przesłać bez znaku? To się tym zaopiekuje. Jeśli nie, przejdź do odpowiedzi templatetypedef. –

25

Jeden z pomysłów wygląda następująco. Załóżmy, że masz wartość czterech bajtów jak ten:

aaaaaaaa bbbbbbbb cccccccc dddddddd 

Załóżmy, że chcesz dostać bajt bbbbbbbb z tego. Jeśli przesunięcie w prawo przez dwa bajty, masz

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

Wartość ta jest równa, co chcesz, z tym że na górze ma ???????? ???????? aaaaaaaa (ponieważ nie jesteśmy pewni, czy zmiana jest logowania zachowaniu lub nie , ponieważ nie wiem, czy twoja wartość jest niepodpisana, czy nie.) Nie martw się; możemy pozbyć się tych nieznanych wartości i bajtu a. Aby pozbyć się górnej załóżmy, że przesunięcie w prawo kolejny bajt, dając

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

Teraz przesunięcie w lewo jeden bajt, aby uzyskać

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

Jeśli następnie zrobić to odejmowanie, masz

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

I voil & agrave; ... masz wartość, którą chcesz!

Zostawię rzeczywisty kod jako ćwiczenie dla czytelnika. Nie martw się; to nie jest szczególnie trudne. :-)

+0

Wydaje się, że masz pomieszane lewy i prawy? –

+0

@ Tom Zych - Ups! Dzięki za złapanie tego. Jestem kiepski w udzielaniu wskazówek. :-) – templatetypedef

+0

@templatetypedef, błędny komentarz pod postem ... lepiej odpocząć na chwilę. ;-). –

0

oto kod:

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

i wyjście:

aa09ca05 
09 
+0

Nie będzie działał na większości kompilatorów, jeśli po prostu użyjesz długich .. – Voo

+0

Specyfikacja ANSI/ISO C mówi, że długo musi mi to co najmniej 4 bajty. Czy znasz dowolny kompilator C zgodny z ANSI, na którym nie będzie działać? –

+3

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

1

Jest bardzo sprytny trik do tego, którego używam do konwersji obiektów do strun Char (do przesyłania jako strumień):

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

W skrócie, powyższe traktuje źródło jako 4 oddzielne znaki (które są normalnie y 1 bajt wielkości), a wskaźnik pozwala traktować go jako sekcję pamięci. Usuwasz ją przed powrotem.

Używaj go w dowolnym celu (nawet komercyjnym).

Skompresowany format?

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

Poniższy kod również powinien odpowiedzieć na pytanie.

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

Wyjście jest

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

Koncepcja można wyjaśnić na podstawie templatetypedef jest wyjaśnienie i rozszerzony w następujący sposób.

(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

Wyjaśnienie, proszę? –

Powiązane problemy