2009-07-24 15 views
3

ich einen DWORD-Wert haben, dass in Hex aussehen könnte:Parsen Bytes (C Windows)

DWORD Val = 0xFF01091A 

Wie kann ich jedes Byte gelesen haben? Was ich meine ist, wie kann ich FF, 01, 09 und 1A lesen?

Danke!

+1

Seien Sie vorsichtig mit dieser Art von Sache, stellen Sie sicher, dass Sie verstehen, woher die Bytes kommen und wenn es das Potenzial gibt, dass der Code auf Nicht-Windows-Plattformen verschieben kann, wo Byte-Reihenfolge unterschiedlich sein kann (von einem großen zu einem kleinen Endian) Prozessor). – Tom

Antwort

2
DWORD x1 = (0xFF01091A & 0xFF000000) >> 24; 
DWORD x2 = (0xFF01091A & 0x00FF0000) >> 16; 
DWORD x3 = (0xFF01091A & 0x0000FF00) >> 8; 
DWORD x4 = (0xFF01091A & 0x000000FF) >> 0; 
+0

Gerade alte Schule! –

+0

Das würde jedoch nicht das richtige Ergebnis geben; Es würde 0xFF000000, 0x00FF0000, 0x0000FF00 und 0x000000FF zurückgeben. Sie müssen auch die Werte bit-shift, also x1 >> = 24, x2 >> = 16 und x3 >> = 8. – JAB

+0

Sie sollten L-Shift um 24, 16, 8 und 0 Bits. –

5
DWORD value; 
// casts to `char *` are always ok: 
unsigned char * bytes = (unsigned char *)&value; 
unsigned char third_byte = bytes[2]; 

Beachten Sie, dass dies die Bytes erhalten werden, wie sie in Erinnerung gebracht werden: Auf Little-Endian-Maschinen bytes[0] wird das niedrigstwertige Byte, auf Big-Endian-Maschinen halten, es wird halten die meisten bedeutender.

Wenn Sie die Bytes nach Signifikanz abrufen möchten, verwenden Sie die Verschiebung wie in Efraim's answer vorgeschlagen.

+0

Schön und einfach, hat aber ein unterschiedliches Verhalten auf Little-Endian- und Big-Endian-Systemen. Ich denke nicht, dass das die Absicht war. – Thorarin

+0

@Thorarin: Kommentar über Endianness hinzugefügt – Christoph

1

AraKs Arbeitsweise funktioniert. Eine andere Art und Weise Sie es tun können, ist:

char x1 = *(((char*)&Val) + 0); 
char x2 = *(((char*)&Val) + 1); 
char x3 = *(((char*)&Val) + 2); 
char x4 = *(((char*)&Val) + 3); 

Achten Sie aber, wird auf diese Weise auf die Bytereihenfolge der Maschine empfindlich sein.

8

Nicht wirklich sein eher wie:

uint8_t Byte1 = (Val>> 0) & 0xFF; 
uint8_t Byte2 = (Val>> 8) & 0xFF; 
uint8_t Byte3 = (Val>>16) & 0xFF; 
uint8_t Byte4 = (Val>>24) & 0xFF; 
+0

Ja, die Verschiebung ist erforderlich, um das richtige Ergebnis zu erhalten +1 –

+0

hoffe, Sie stört mich nicht die Formatierung beheben – Christoph

+0

Ihr Weg ist tatsächlich sauberer :) – AraK

1

Maske und Verschiebung (wie in einer früheren Antwort vorgeschlagen) arbeitet; eine etwas knifflige Alternative ist „Zeigertyp punning“, das heißt

xlowbyte = (unsigned char*)(&Val) [0]; /* LSB, 0x1A */ 
xmidlowb = (unsigned char*)(&Val) [1]; /* 2nd-LSB, 0x09 */ 

etc - vorausgesetzt, Sie auf einer Little-Endian-Maschine sind (was wahrscheinlich ist, wenn Sie Windows verwenden).

2

Verwenden Sie eine Vereinigung:

union Bytes { 
    char c[4]; 
    unsigned int n; 
}; 

int main() { 
    Bytes b; 
    b.n = 0xFF01091A; 
    char c = b.c[2]; 
} 

Edit: Sorry, das ist C++ Code. Ich bin zu müde, um es in C umzuwandeln und es zu testen, aber du hast die Idee?

+0

nicht viel Konvertierung zu tun: es gibt eine 'union' fehlt vor' Bytes b; 'und Sie sollten' main' als 'int main (void)' zu erklären – Christoph