9

Ich mache Embedded ARM-Programmierung mit gcc 4.9. Ich habe den Schalter -Wconversion verwendet, weil er in der Standard-Dev-Tool-Konfiguration meines Unternehmens ist. Ich benutze die stdint.h types (uint8_t, uint32_t, etc).Verwenden von Typecasting zum Entfernen von GCC-Compiler-Warnungen

Der Compiler erstellt Warnungen jedes Mal, wenn ich eine zusammengesetzte Zuweisung oder sogar einfache Addition durchführen. Zum Beispiel:

uint8_t u8 = 0; 
uint16_t u16; 

// These cause warnings: 
u8 += 2; 
u8 = u16 >> 8; 

Die „übliche Methode“, dies zu beheben ist Abgüsse zu verwenden, wie here und here diskutiert:

u8 = (uint8_t)(u8 + 2); 
u8 = (uint8_t)(u16 >> 8); 

Zusätzlich dazu ist hässlich, ich immer in überzeugenden Beweis ausgeführt wird, Casting ist in der Regel eine schlechte Übung.

Meine Fragen:

  1. Warum ist es schlecht Typumwandlungen auf diese Weise zu benutzen?
  2. Verliere ich alles, indem ich einfach -Wconversion weglasse und den Compiler implizite Konvertierungen für mich machen lasse?
+0

In diesem Fall gibt es nichts Schlimmes an der Typisierung. Wenn überhaupt, zeigt es, dass Sie die Semantik, die arithmetische Wrap-around-Funktion, die Trunkierung usw. berücksichtigt haben - und Sie sind damit zufrieden. –

+0

@BrettHale, mindestens behauptet der Cast *, dass Sie alle Implikationen berücksichtigt haben und mit ihnen zufrieden sind. Selbst wenn Sie nicht oder nicht haben. –

+1

@BrettHale, könnten Sie die Besetzung dort setzen, wenn Sie mehr über das Schließen des Compilers als über möglichen fehlerhaften Code interessieren (nicht spotten - es geschieht). Sie könnten es auch tun, wenn Sie glauben, Sie hätten alle Konsequenzen berücksichtigt, aber Sie irren sich. Oder auch wenn Sie es einfach nicht besser wissen. Ich stimme zu, dass das Casting nicht von Natur aus, notwendigerweise * schlecht * ist, aber die Notwendigkeit zu vermeiden, an erster Stelle zu wirken, ist * besser *. –

Antwort

3

Der Compiler zeigt Ihnen mögliche Problemstellen, die Sie ändern sollten, aber nicht durch Umwandlungen. Das Problem in dem Code, den Sie haben, ist, dass in C Arithmetik nie für Typ ausgeführt wird, der schmaler ist als int: der Compiler führt immer eine implizite Konvertierung in int für sie durch.

So effektiv konvertiert der Code die schmalen vorzeichenlosen Typen in int, führt die Operation aus und konvertiert sie dann wieder in den unsigned-Typ.

Im Allgemeinen Arithmetik mit engen Typen ist keine gute Idee. Verwenden Sie sie nur, wenn die Speichergröße ein Problem ist (normalerweise sind das größere Strukturen wie Arrays). Für lokale, mehr oder weniger temporäre Variablen machen diese engen Typen keinen Sinn.

3

Es ist eine Frage des Geschmacks. Eine Umwandlung wird von C nie benötigt, wenn Sie einem Objekt eines anderen arithmetischen Typs einen Wert eines arithmetischen Typs zuweisen. Manche Leute benutzen die Besetzung, um zu dokumentieren, dass es eine versteckte Konvertierung gibt und dass sie es absichtlich getan haben.

Persönlich mag ich nicht besonders unnützes Zeug legen und ich nehme an, der Leser die Grundlagen der C weiß, so neige ich dazu, die Besetzung zu vermeiden (und ich verwende -Wconversion nicht, welche nicht Teil -Wall oder sogar -Wextra sowieso). Beachten Sie, dass in einer Zuweisung, wenn ein Literal auf der rechten Seite nicht in das linke Objekt passt gcc normalerweise warnt (ohne -Wall oder -Wextra), auch wenn die Zuweisung nicht UB ist.

2

Das Problem mit Umwandlungen ist, dass sie dem Compiler sagen "Halt die Klappe, ich weiß, was ich tue", auch wenn du es nicht tust. Wenn jemand entscheidet, dass die Variable mit Werten größer als 255 umgehen und den Typ in uint16_t ändern kann, würde u8 + = 2 funktionieren, aber u8 = (uint8_t) (u8 + 2) wäre defekt. Unter der Annahme, dass die Variable nicht zB u8, sondern "numberOfParagraphs" heißt, könnte dies ein Fehler sein, der sehr schwer zu finden ist.

Besser, einen größeren Typ an erster Stelle zu verwenden. Es sei denn, Sie möchten wirklich (u8 + 2) & 0xff speichern, in diesem Fall können Sie es so schreiben und es in eine größere Variable ohne Probleme speichern.

(Ich persönlich würde eine Erweiterung der Sprache mag wie

(uint8_t)u8 += 2; 

mit der Semantik, die einen L-Wert auf seine eigene Art hat keine Wirkung Gießen und es bleibt ein L-Wert, während die Warnung zu entfernen, aber Gießen eines lvalue zu einem anderen Typ würde ein Fehler sein.Dies würde es sicher machen, die Compiler-Warnung zu stoppen)

Verwandte Themen