Ich habe kürzlich ein Makro geschrieben, um dies in C zu tun, aber es ist auch in C ++ gültig:
#define REVERSE_BYTES(...) do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(__VA_ARGS__)>>1; ++REVERSE_BYTES)\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES];\
while(0)
Es akzeptiert jeden Typ und kehrt die Bytes im übergebenen Argument um. Beispielverwendungen:
int main(){
unsigned long long x = 0xABCDEF0123456789;
printf("Before: %llX\n",x);
REVERSE_BYTES(x);
printf("After : %llX\n",x);
char c[7]="nametag";
printf("Before: %c%c%c%c%c%c%c\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6]);
REVERSE_BYTES(c);
printf("After : %c%c%c%c%c%c%c\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6]);
}
Welche Drucke:
Before: ABCDEF0123456789
After : 8967452301EFCDAB
Before: nametag
After : gateman
Das Obige ist perfekt kopierbar / einfügbar, aber hier ist viel los, also werde ich Stück für Stück aufschlüsseln, wie es funktioniert:
Das erste Bemerkenswerte ist, dass das gesamte Makro in einem do while(0)
Block eingeschlossen ist. Dies ist eine gängige Redewendung , um die normale Verwendung von Semikolons nach dem Makro zu ermöglichen.
Als nächstes wird eine Variable verwendet, die REVERSE_BYTES
als for
Zähler der Schleife bezeichnet wird. Der Name des Makros selbst wird als Variablenname verwendet, um sicherzustellen, dass er nicht mit anderen Symbolen in Konflikt gerät, die möglicherweise überall dort verwendet werden, wo das Makro verwendet wird. Da der Name in der Makroerweiterung verwendet wird, wird er nicht erneut erweitert, wenn er hier als Variablenname verwendet wird.
Innerhalb der for
Schleife werden zwei Bytes referenziert und XOR ausgetauscht (daher ist kein temporärer Variablenname erforderlich):
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES]
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES]
__VA_ARGS__
stellt alles dar, was dem Makro gegeben wurde, und wird verwendet, um die Flexibilität dessen zu erhöhen, was übergeben werden kann (wenn auch nicht viel). Die Adresse dieses Arguments wird dann genommen und in einen unsigned char
Zeiger umgewandelt, um das Austauschen seiner Bytes über ein Array zu ermöglichen[]
Subskription zu ermöglichen.
Der letzte besondere Punkt ist das Fehlen von {}
Zahnspangen. Sie sind nicht erforderlich, da alle Schritte in jedem Swap mit dem Komma-Operator verknüpft sind , was sie zu einer Anweisung macht.
Schließlich ist anzumerken, dass dies nicht der ideale Ansatz ist, wenn Geschwindigkeit oberste Priorität hat. Wenn dies ein wichtiger Faktor ist, sind einige der typspezifischen Makros oder plattformspezifischen Anweisungen, auf die in anderen Antworten verwiesen wird, wahrscheinlich die bessere Option. Dieser Ansatz ist jedoch auf alle Typen, alle wichtigen Plattformen sowie auf die Sprachen C und C ++ portierbar.