zwei 8bit Werte in ein 16bit Wert umwandeln Warnung (C)

OP Persönliche Seite #6576618
Lesenswert?

Moin,

bitte entschuldigt wenn ich hier für einige Meister der Programmierung 
eine viel zu triviale Frage stelle und allein deswegen Spot, Empörung 
oder Belustigung auslöse. :D

Ich habe ein uint8_t Array der Größe zwei und ich möchte eine uint16_t 
Variable mit dem Inhalt des Arrays füllen.

Ich tat dies so:
1
uint8_t array[2] = {0x22, 0x66};
2
uint16_t b = array[0]<<8 | array[1];
3
printf("0x%04X\n", b);
4

5
--> 0x2266

Der Compiler warnt mich das:
1
Warnung: Umwandlung von »int« nach »uint16_t« {aka »short unsigned int«} könnte den Wert ändern [-Wconversion]

Kann ich die Warnung in diesem Fall einfach ignorieren weil der Compiler 
anscheinend nicht weiß das ich zwei uint8_t zu einem uint16_t vereinen 
möchte oder ist meine Umwandlung nicht gut gemacht und man macht das 
generell anders?
#6576642
Lesenswert?

Das Problem liegt darin, dass die Integer-Promotion dazu führt, dass die 
Berechnung mit dem Typ int durchgeführt wird. array[0]<<8 kann dann aber 
zu einem negativen Wert führen. Du müsstest mindestens eines der beiden 
Elemente nach uint16_t casten, damit die Berechnung damit ausgeführt 
wird. Dann verschwindet auch die Warnung.
Gast #6576644
Lesenswert?

Es ist gut, dass Du Warnungen an hast und sie ernst nimmst.

Was hier passiert: integer promotion sorgt dafür, dass aus dem uint8 
beim schieben ein int wird.

Sauber wäre, dass Array-Element zuerst auf uint16 zu casten.

Hier stört es nicht, aber du solltest es wissen.
Beitrag #6576652 wurde von einem Moderator gelöscht.
Beitrag #6576653 wurde von einem Moderator gelöscht.
#6576658
Lesenswert?

Ein CAST könnte helfen :
1
uint8_t array[2] = {0x22, 0x66}; 
2

3
uint16_t b = (uint16_t)(array[0]<<8) | (uint16_t)array[1]; 
4
printf("0x%04X\n", b);

Schließlich sollte man wissen was der CAST bewirkt. Man gibt dem 
Kompiler bekannt, dass es sich rechts um zwei Variable vom Typ  uint16 
handelt. Der Kompiler gibt dann keine Warnung mehr aus. Det CAST muss 
link und rechts vom "oder" befindlichen Werte durchgefühert werden, 
damit schon uint16 Werte miteinander vorodert werden.

Warnungen generell abzuschalten ist keine gute Lösung.
Gast #6576734
Lesenswert?

Gerald K. schrieb:
> Det CAST muss
> link und rechts vom "oder" befindlichen Werte durchgefühert werden,
> damit schon uint16 Werte miteinander vorodert werden.

Das ist nicht richtig, siehe

Rolf M. schrieb:
> Du müsstest mindestens eines der beiden
> Elemente nach uint16_t casten, damit die Berechnung damit ausgeführt
> wird. Dann verschwindet auch die Warnung.

Ein Problem ist, dass casts eigentlich böse sind. Sie schalten praktisch 
alle Warnungen ab.

Von daher kann es sinnvoll sein, hier ohne Integer-Promotion und ohne 
casts zu arbeiten. So bleibt Warnungen bei Flüchtigkeits-Fehlern 
trotzdem erhalten:

Variante 1: Hilfsvariable
1
uint16_t h = array[0];        
2
uint16_t b = h<<8 | array[1];

Variante 2: zweistufig
1
uint16_t b = array[0];        
2
b = h<<8 | array[1];

Variante 3: eine Verknüpfung mit 0U macht alles unsigned
1
uint16_t b = 0U | array[0]<<8 | array[1];
Beitrag #6576740 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren