2016-08-04 21 views
0

bekam ich ein ProgrammShop-Werte in 64-Bit-Integer in C

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

int main(void) 
{ 

int i; 
int x = 128; 
int y = 128; 
int z = 2; 
int32_t coordinates = x | (y << 12) | (z << 16); 

fprintf(stdout, "x = %d\n", (coordinates & 0xFF)); 
fprintf(stdout, "y = %d\n", ((coordinates >> 8) & 0xFF)); 
fprintf(stdout, "z = %d\n", ((coordinates >> 16) & 0xFF)); 
} 

Das speichert x,y,z in 32-Bit-Register, aber seine erfolgreiche NUR für { (x,y,z)< 256}. Wenn ich möchte, dass x,y,z Werte von 2^10 (1024) (also (x,y,z)<1024) erhalten kann, wie kann das passieren? Ich weiß, dass ich ein 64-Bit-Register (?) Verwenden sollte, aber ich stecke darauf fest, weil etwas mit Schichten vor sich geht.

Irgendwelche Ideen?

+1

Sie ein 64-Bit-Variable und beide verwenden sollen ... nur Verschiebung und Masken ändern. 1024 ist 10 Bits, dann um 10 und dann um 20 und Maske mit 0x3FF –

+1

Es * kann sein * * int64_t/uint64_t Typen in 'stdint.h' (aber sie sind nicht obligatorisch). –

+0

Ihr Code ruft undefiniertes Verhalten auf Plattformen mit 'int' auf, die z. 16 Bits. Im Allgemeinen ist es eine schlechte Idee, vorzeichenbehaftete ganze Zahlen zu verschieben, es sei denn, Sie können garantieren, dass diese Verschiebungen niemals undefiniertes Verhalten auslösen. Was bedeutet, bestimmte Werte/Schicht-Anzahl-Kombinationen zu vermeiden. – Olaf

Antwort

1
  1. Anstatt verwenden Typen unterzeichnet, unsigned Typen verwenden. Viel weniger Ärger. @Olaf

  2. Der folgende Code ermöglicht x einen 12-Bit-Bereich zu haben, bevor er mit y kollidiert. Es erlaubt y einen 4-Bit (16 - 12) Bereich zu haben, bevor es mit z kollidiert. Es hat Probleme mit einem 16-Bit int/unsigned.

    int32_t coordinates = x | (y << 12) | (z << 16); 
    

Damit x,y,z einen Bereich von 10-Bit aufweisen, verschieben y von 10 und z von 10 + 10.

uint32_t coordinates = x | ((uint32_t)y << 10) | ((uint32_t)z << 20); 

Um die Werte exakt:
(achten Sie auch den passenden Druck Spezifizierer verwenden.)

#include <inttypes.h> 
... 
fprintf(stdout, "x = %" PRIu32 "\n", (coordinates & 0x3FF)); 
fprintf(stdout, "y = %" PRIu32 "\n", ((coordinates >> 10) & 0x3FF)); 
fprintf(stdout, "z = %" PRIu32 "\n", ((coordinates >> 20) & 0x3FF)); 
+0

Mit unsigned Int 32 Bit, wird jedes Problem beim Senden mit MPI sein? Oder sollte ich lieber unterschrieben haben? – BillG

+0

@BillG In diesem Fall könnte der Code "int32_t" auch mit "uint32_t" verwenden, da 2 obere Bits nicht verwendet werden. Verwenden Sie 'uint32_t' als Teil Ihrer [MPI] (https://en.wikipedia.org/wiki/Message_Passing_Interface) falls möglich, ändern Sie andernfalls wieder zu' int32_t'. Ich vermute, dass "int32_t" favorisiert ist - aber ich müsste mehr Code sehen, um die beste Antwort zu erhalten. – chux

1

Wenn Sie 3 Felder von 10 Bits haben, werden diejenigen, die in einem 32-Bit-int passen . Sie können es wie folgt:

int32_t coordinates = (int32_t)(x & 0x3ff) | 
         ((int32_t)(y & 0x3ff) << 10) | 
         ((int32_t(z & 0x3ff) << 20); 

Sie zuerst eine bitweise durchzuführen und von 0x3ff mit jeder Zahl, um sicherzustellen, nur die untersten 10 Bits erhalten. Das Ergebnis wird dann an den Typ des Ergebnisses übergeben, um sicherzustellen, dass bei der Verschiebung des Werts die Zwischenwerte nicht zu weit verschoben werden. Dann wird jeder Wert an einem 10-Bit-Offset über Verschiebungen platziert.

Dann können Sie sie wieder aus wie folgt lauten:

fprintf(stdout, "x = %d\n", (coordinates & 0x3FF)); 
fprintf(stdout, "y = %d\n", ((coordinates >> 10) & 0x3FF)); 
fprintf(stdout, "z = %d\n", ((coordinates >> 20) & 0x3FF));