2012-09-02 23 views
10

Ich habe ein Zeichenfeld ohne Vorzeichen [248]; gefüllt mit Bytes. Wie 2F AF FF 00 EB ABCD EF ..... Dieses Array ist mein Byte-Stream, in dem ich meine Daten vom UART (RS232) als Puffer abspeichere.Konvertieren von Bytes zu Int/uint in C

Jetzt möchte ich die Bytes wieder in meine Uint16 und Int32 konvertieren.

In C# habe ich die BitConverter-Klasse dazu verwendet. Beispiel:

byte[] Array = { 0A, AB, CD, 25 }; 
int myint1 = BitConverter.ToInt32(bytes, 0); 
int myint2 = BitConverter.ToInt32(bytes, 4); 
int myint3 = BitConverter.ToInt32(bytes, 8); 
int myint4 = BitConverter.ToInt32(bytes, 12); 
//... 
enter code here 
Console.WriteLine("int: {0}", myint1); //output Data... 

Gibt es eine ähnliche Funktion in C? (Kein .net, verwende ich den KEIL Compiler, weil Code auf einem Mikrocontroller läuft)

Mit freundlichen Grüßen Sam

Lösungen: Way A)

zuerst musste ich konvertieren oder das Array zu initialisieren ein uint8_t ARRAY [248]; Dann habe ich diesen Code mit Ihrer Hilfe:

uint32_t* myint1 = (uint32_t *)&RXBUFF[2]; //test 
uint16_t* myint2 = (uint16_t *)&RXBUFF[6]; //test3 

Achtung: Der int-Wert "1985" in hex als 0x07C1 in myint2 vertreten. das Byte, das ich sendete, war "C1 07", also ändert der Mikrocontroller die Byte-Reihenfolge

Ich werde die anderen Methoden auch prüfen.

WR Sam :)

Antwort

8

Ja, gibt es. Angenommen, Ihre Bytes sind in:

uint8_t bytes[N] = { /* whatever */ }; 

Wir wissen, dass ein 16-Bit-Integer ist nur zwei 8-Bit-Integer verkettet, das heißtman hat ein Vielfaches von 256 oder alternativ durch 8 verschoben wird:

uint16_t sixteen[N/2]; 

for (i = 0; i < N; i += 2) 
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8; 
      // assuming you have read your bytes little-endian 

Ähnlich für 32 Bits:

uint32_t thirty_two[N/4]; 

for (i = 0; i < N; i += 4) 
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8 
     | ((uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24; 
      // same assumption 

Wenn die Bytes gelesen big-endian, natürlich die Reihenfolge umkehren :

bytes[i+1] | (uint16_t)bytes[i] << 8 

und

bytes[i+3] | (uint32_t)bytes[i+2] << 8 
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24 

Beachten Sie, dass es einen Unterschied zwischen der Endian-Ness in der gespeicherten Ganzzahl und der Endian-Ness der laufenden Architektur gibt. Die Endian-Eigenschaft, auf die in dieser Antwort Bezug genommen wird, ist die gespeicherte Ganzzahl, d. H. Der Inhalt von bytes. Die Lösungen sind unabhängig von der Endian-Ness der laufenden Architektur seit endian-ness is taken care of when shifting.

+0

was ist wenn sein großer Endian? – Sam

+0

dann verschieben Sie die niedrigstwertigen Bits anstelle der höchstwertigen Bits. – devsnd

+0

@twall, ich denke du meinst Bytes. –

15

Es gibt keine Standardfunktion, die für Sie in C tun, werden Sie die Bytes wieder in Ihre 16- und 32-Bit-Integer zusammenstellen müssen, um sich selbst. Sei vorsichtig mit Endianness!

Hier ist ein einfaches Little-Endian Beispiel:

extern uint8_t *bytes; 
uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24); 

Für ein Big-Endian-System, es ist genau das Gegenteil um:

uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3]; 

Sie könnten mit wegkommen können:

uint32_t myInt1 = *(uint32_t *)bytes; 

Wenn Sie bei Ausrichtungsproblemen vorsichtig sind.

+1

Ich würde jedes 'bytes []' auf ein 'uint32_t' werfen, bevor ich es verschiebe. Wie oben beschrieben, werden sie vor der Umschaltung in "int" umgewandelt, aber "int" muss nicht 32 Bit lang sein. –

+0

Das wäre am sichersten, einverstanden. –

+0

Angenommen, Bytes sind native Endian, auf welche Art von Ausrichtungsproblemen würden Sie stoßen? Oder, ich denke, welche Art von Situationen macht die Ausrichtung zu einem Problem? – Azmisov

6

Sie können einen uint16_t * -Zeiger direkt von Ihrem Array erstellen.

uint8_t bytes[N] = { /* whatever */ }; //Shamelessly stolen from Shanbaz 

uint16_t* viewAsUint16_t = (uint16_t *)&bytes[0]; 

Jetzt können Sie den Zeiger verwenden, um auf die Elemente zuzugreifen.

Beachten Sie, dass dies davon ausgeht, dass die Endlichkeit für Ihr Gerät korrekt ist. Sie müssen möglicherweise diese uint16_t s durchlaufen und eine Funktion wie ntohs verwenden (sollte auf den meisten Betriebssystemen verfügbar sein), um Endlichkeit zu korrigieren.

+0

ich werde das jetzt versuchen. – Sam

+0

Ich habe versucht, Ihren Code, aber es scheint, es hat nicht funktioniert. Ich habe die Ausgabe vom Debugger und der Konsole als Bild gespeichert: [link] (http://s18.postimage.org/fipv7svp3/debugbyte.png) – Sam

0
  char letter = 'A'; 
      size_t filter = letter; 
      filter = (filter << 8 | filter); 
      filter = (filter << 16 | filter); 
      filter = (filter << 32 | filter); 
      printf("filter: %#I64x \n", filter); 

Ergebnis: "Filter: 0x4141414141414141"

0

Bei Little-Endian, können Sie nicht nur memcpy verwenden?

memcpy((char*)&myint1, aesData.inputData[startindex], length); 
Verwandte Themen