Forum: PC-Programmierung zwei 8bit Werte in ein 16bit Wert umwandeln Warnung (C)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Paul G. (paul_g210) Benutzerseite


Bewertung
0 lesenswert
nicht 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?

: Bearbeitet durch User
von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht 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.

von A. S. (achs)


Bewertung
1 lesenswert
nicht 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.
von Rolf M. (rmagnus)


Bewertung
6 lesenswert
nicht lesenswert
Felix schrieb im Beitrag #6576652:
> solche warnungen kannst du einfach deaktivieren. die stören nur beim
> coden.

Ja, kannste schon machen, aber dann ist es halt Sch****.

von Gerald K. (geku)


Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
von Paul G. (paul_g210) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Integer-Promotion


Danke euch, wieder was gelernt.

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

Det mach ich so.

von dummtipper (Gast)


Bewertung
0 lesenswert
nicht lesenswert
eventuell hilft schon, ein U hinter die 8 zu schreiben

von A. S. (achs)


Bewertung
0 lesenswert
nicht 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.
von Robinson Caruso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wenn int auch 2 Byte groß ist, dann kann es schiefgehen. (Wenn die Zahl 
nicht mehr durch signed int dargestellt werden kann)

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Robinson Caruso schrieb:
> Wenn int auch 2 Byte groß ist, dann kann es schiefgehen. (Wenn die Zahl
> nicht mehr durch signed int dargestellt werden kann)

was kann beim bisherigen Code schiefgehen und warum? Oder meinst Du wenn 
man andere Sachen (Vergleiche oder Dergleichen) macht?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.