2017-09-09 3 views
2
unsigned long swap_bytes(unsigned long n) { 
    unsigned char bytes[8]; 
    unsigned long temp; 
    bytes[0] = (n >> ??) & 0xff; 
    bytes[1] = (n >> ??) & 0xff; 
    // ... 
} 

Ich bin wirklich verwirrt, wie ein 8-Byte-unsigned long von ex verschieben: 0x12345678deadbeef-0x34127856addeefbe. Ich habe angefangen, aber ich bin jetzt festgefahren. Bitte helfen Sie.Swap Bytes innerhalb eines unsigned long (8 Bytes) in C

+0

'unsigned long' ist wahrscheinlich nicht breit genug, um' 0x12345678deadbeef' zu enthalten. Meinst du "unsigned long long"? –

+0

Fahren Sie fort, wie Sie begonnen haben. Verschieben und maskieren Sie jedes Byte in das Array und erstellen Sie das Ergebnis komplementär. 'unsigned' war eine gute Wahl. –

+0

'long' ist * mindestens * die Größe von' int'. Ich empfehle Ihnen, printf ("% zu \ n", sizeof (lang)) ', um das festzustellen. –

Antwort

0

könnten Sie versuchen, diese

void swap(char *ptr, int i, int j) 
{ 
    char temp=*(ptr+i); 
    *(ptr+i)=*(ptr+j); 
    *(ptr+j)=temp; 
} 
int main() 
{ 
    //unsigned long n = 0x12345678deadbeef; 
    uint64_t n = 0x12345678deadbeef; 

    char *ptr=(char *)&n; 

    swap(ptr, 0, 1); 
    swap(ptr, 2, 3); 
    swap(ptr, 4, 5); 
    swap(ptr, 6, 7); 
} 

Die Adresse n in einen char Zeiger gegossen und in ptr gespeichert.

ptr+i wird die Adresse des i te Byte von n, deren Wert (dh *(ptr+i)) geben in geeigneter Weise durch die swap() Funktion modifiziert wird.

Edit: Wenn Sie nicht sicher sind, ob Ihre unsigned long 's Größe 8 Bytes ist, können Sie uint64_t von inttypes.h verwenden.

+1

Ich denke, du solltest bearbeiten, um 'uint_64' anstelle von' long' zu verwenden. –

+0

... oder sogar 'uint64_t'. –

5

Sie können jedes andere Byte in beiden Versionen mit & binär UND maskieren.
Dann verschieben Sie beide maskierten Werte in entgegengesetzte Richtungen und kombinieren Sie sie mit | binär ODER.

n = ((n & 0xff00ff00ff00ff00ull)>>8ull) 
    | ((n & 0x00ff00ff00ff00ffull)<<8ull); 

Falls es ist 4Byte (was ich ein unsigned long im Gegensatz zum unsigned long long betrachten, aber das ist die Umsetzung spezifisch), dann ist der Code

n = ((n & 0xff00ff00ul)>>8ul) 
    | ((n & 0x00ff00fful)<<8ul); 
+1

Großer Einliner! –

+0

Das macht für mich Sinn. Ich danke dir sehr. Aber warum zeigt sich mein Wert von n als 4050765991979987505? Anstelle von 12345678deadbeef? Die vertauschte Antwort lautet 3978988777685397810 anstelle von 34127856addeefbe. Warum das? – dp123

+0

Sehen Sie sich die printf-Doku an, um zu erfahren, wie Sie alle möglichen Größen drucken können und, falls gewünscht, in hex. In meinem Test habe ich 'printf ("% I64x \ n ", n);' mit gcc windows verwendet. – Yunnosch

0

universal & schrecklich

void swapbytes(void *p, size_t size) 
{ 
    uint8_t tmp, *ptr = p; 

    for (size_t i = 0; i < (size - 1); i += 2) 
    { 
     tmp = *(ptr + i); 
     *(ptr + i) = *(ptr + i + 1); 
     *(ptr + i + 1) = tmp; 
    } 
} 

Verwendung:

uint64_t n; 


swapbytes(&n, sizeof n); 
+0

Was ist los mit OP-Ansatz mit Schichten? Schließlich sind sie nicht implementierungsspezifisch und rufen kein undefiniertes Verhalten auf, wie bei Ihrem ersten Ansatz. Schrecklich - in der Tat. – Olaf