2011-12-30 22 views

Odpowiedz

14

można uzyskać za pomocą bajtów trochę arytmetyki wskaźników:

int x = 12578329; // 0xBFEE19 
for (size_t i = 0; i < sizeof(x); ++i) { 
    // Convert to unsigned char* because a char is 1 byte in size. 
    // That is guaranteed by the standard. 
    // Note that is it NOT required to be 8 bits in size. 
    unsigned char byte = *((unsigned char *)&x + i); 
    printf("Byte %d = %u\n", i, (unsigned)byte); 
} 

Na moim komputerze (Intel x86-64), wyjście jest:

Byte 0 = 25 // 0x19 
Byte 1 = 238 // 0xEE 
Byte 2 = 191 // 0xBF 
Byte 3 = 0 // 0x00 
+1

Jak 4294967278 to bajt? Domyślny typ 'char' jest prawdopodobnie podpisany w twoim systemie, a rzutowanie na' unsigned' daje duże liczby. –

+0

@Eser Aygün Zaktualizuję kod. Dziękuję za komentarz. –

+0

Czy istnieje jakikolwiek powód używania arytmetyki wskaźnika ręcznego zamiast znacznie bardziej czytelnego dostępu do tablicy? –

3

Jeśli chcesz uzyskać te informacje, powiedzmy:

int value = -278; 

(Wybrałem tę wartość, ponieważ nie jest bardzo interesujące ing dla 125 - najmniej znaczący bajt jest 125, a pozostałe bajty są wszystkie 0)

Najpierw trzeba wskaźnik do tej wartości:

int* pointer = &value; 

Teraz można typecast, że do „char” wskaźnik! który jest tylko jeden bajt i pobiera poszczególne bajty przez indeksowanie.

for (int i = 0; i < sizeof(value); i++) { 
    char thisbyte = *(((char*) pointer) + i); 
    // do whatever processing you want. 
} 

Zauważ, że kolejność bajtów na int i innych typów danych zależy od systemu - look up „grubokońcej” vs „little-endian”.

+0

Czy istnieje jakikolwiek powód używania arytmetyki wskaźnika ręcznego zamiast znacznie bardziej czytelnego dostępu do tablicy? –

+0

Ponieważ jest to oczywiste dla tych, którzy są wykształceni, ponieważ używamy wskaźnika? Nie uważam arytmetycznej wskaźnika za błędną lub nieczytelną. – Dan

+1

To nie jest złe, ale z pewnością nie twierdzisz, że jest tak czytelny jak dostęp do tablicy ...! Porównaj '* (x + i)' z 'x [i]'. W rzeczywistości, dlaczego w ogóle istnieje składnia dostępu do tablicy, jeśli nie używamy jej w razie potrzeby? –

2

To powinno działać:

int x = 125; 
unsigned char *bytes = (unsigned char *) (&x); 
unsigned char byte0 = bytes[0]; 
unsigned char byte1 = bytes[1]; 
... 
unsigned char byteN = bytes[sizeof(int) - 1]; 

Ale należy pamiętać, że kolejność bajtów liczb całkowitych jest platforma zależne.

+0

Zamawianie bajtów zależy od procesora, nie zależy od systemu operacyjnego. – DipSwitch

+0

@DipSwitch Masz rację. Poprawione. –

3

Można skorzystać z union ale należy pamiętać, że kolejność bajtów jest procesor zależne i nazywa endianness http://en.wikipedia.org/wiki/Endianness

#include <stdio.h> 
#include <stdint.h> 

union my_int { 
    int val; 
    uint8_t bytes[sizeof(int)]; 
}; 

int main(int argc, char** argv) { 
    union my_int mi; 
    int idx; 

    mi.val = 128; 

    for (idx = 0; idx < sizeof(int); idx++) 
     printf("byte %d = %hhu\n", idx, mi.bytes[idx]); 

    return 0; 
} 
+0

@WTP ah lol, nawet nie zauważyłem: p – DipSwitch

14

Musisz znać liczbę bitów (często 8) w każdym „bajt ". Następnie możesz wyodrębnić każdy bajt po kolei, używając AND z odpowiednią maską. Wyobraźmy sobie, że int ma 32 bity, a następnie dostać 4 bajty z the_int:

int a = (the_int >> 24) & 0xff; // high-order (leftmost) byte: bits 24-31 
    int b = (the_int >> 16) & 0xff; // next byte, counting from left: bits 16-23 
    int c = (the_int >> 8) & 0xff; // next byte, bits 8-15 
    int d = the_int   & 0xff; // low-order byte: bits 0-7 

I to wszystko: każdy bajt jest w niskim rzędu 8 bitów a, b, c i d.

+0

Robisz to trudniej niż jest, a używanie przesuwania do wyodrębniania bajtów jest raczej obciążające procesor. Byłoby o wiele prostsze i szybsze uzyskanie dostępu do każdej bajtowej lokalizacji bezpośrednio w pamięci ... – DipSwitch

+0

@Dip - mój brutalny sposób ma zaletę, że jest przenośny w procesorach, podczas gdy inne mogą nie być. Ale jak chcesz, oczywiście. –

+1

+1: Uważam, że jest to o wiele lepsze niż manipulowanie z lokalizacją w pamięci. 1) jeśli jest agnostykiem endi. 2) Procesor może wykonywać operacje w rejestrach procesorów, więc zwykle jest znacznie bardziej wydajny. W rzeczywistości, dla niektórych (8-bitowych) maszyn, może to nie generować żadnego kodu (jeśli masz porządny kompilator). – Lindydancer

Powiązane problemy