mikrocontroller.net

Forum: Compiler & IDEs avr-gcc: Warnung bei fehlendem Cast aktivieren?


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.
Autor: Manfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich sowas schreibe, kriege ich keine Warnung. Ist das so gewollt?
for (uint8_t i = 0; i < 32; i++) {
   uint32_t mask = 1 << i;
   // ...
}

Welcher Kommandozeilenparameter muss angegeben werden, damit eine 
Warnung erscheint?

Autor: Name (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Anders gefragt. Warum erwartest du eine Warnung?

Autor: Name (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Lass einmal die for weg. Erwartest du auch hierbei eine Warnung?
uint32_t var = 88

Autor: Jemand (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Name schrieb:
> Anders gefragt. Warum erwartest du eine Warnung?

Ggf. ist int nur 16 Bit groß, dann wäre der Code so fehlerhaft.

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist so gewollt, da mit -Wsign-conversion zu viele Meldungen kommen ;-)

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Name schrieb:
> Anders gefragt. Warum erwartest du eine Warnung?

Ich vermute, es geht darum, dass 1 und damit auch 1 << i vom Typ int 
ist. Man müsste eigentlich UINT32_C(1) << i schreiben. Bei einem 
32-Bit-int führt 1 << 31 zu undefiniertem Verhalten. Beim AVR ist int 
sogar nur 16 Bit breit.

: Bearbeitet durch User
Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bei einem 32-Bit-int führt 1 << 31 zu undefiniertem Verhalten.

Ist nicht sogar jeglicher left-shift eines signed Typen undefiniert? 
Eine gcc-Warn-Option dafür ist mir aber nicht bekannt (wäre wohl noch 
unpopulärer als -Wsign-conversion ;-) ).

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
foobar schrieb:
>> Bei einem 32-Bit-int führt 1 << 31 zu undefiniertem Verhalten.
>
> Ist nicht sogar jeglicher left-shift eines signed Typen undefiniert?

Nein, nur wenn der zu schiebende Wert negativ ist oder das Ergebnis der 
entsprechenden Multiplikation mit 2ᶦ vom Typ nicht repräsentiert werden 
kann.

: Bearbeitet durch User
Autor: Oliver S. (oliverso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jemand schrieb:
> Name schrieb:
>> Anders gefragt. Warum erwartest du eine Warnung?
>
> Ggf. ist int nur 16 Bit groß, dann wäre der Code so fehlerhaft.

Beim avr-gcc ist das so.

Oliver

: Bearbeitet durch User
Autor: Manfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es doch 
eine Warnung geben...

Autor: test (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manfred schrieb:
> Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es
> doch eine Warnung geben...

Da müsste der gcc aber schon sehr clever sein um hier das Problem zu 
sehen. Kann man so etwas heutzutage erwarten?

Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen. 
D.h. wenn man mit Bits rummacht sollte man generell wissen was für 
Datentypen man da benutzt.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
test schrieb:
> Kann man so etwas heutzutage erwarten?
>
> Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen.

Darüber kann man gespaltener Meinung sein. Es gibt auch die Theorie 
derzufolge es das Ziel sein sollte eine Sprache (oder in Ermangelung 
einer neuen Sprache dann halt eben einen Compiler für eine existierende) 
so zu entwerfen daß der Programmierer bestimmte (möglichst viele) Arten 
von Fehlern schlichtweg einfach nicht mehr machen kann da man 
mittlerweile gelernt hat daß menschliche Programmierer zwar unglaublich 
clevere Algorithmen ersinnen können aber dennoch immer wieder so blöde 
kleine Flüchtigkeitsfehler machen.

Das resoniert auch gut mit der Utopie daß eigentlich die Maschinen dem 
Menschen dienen sollen und nicht umgekehrt.

: Bearbeitet durch User
Autor: Manfred (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Schaut euch mal die ersten Kommentare an. Ich hatte meine Frage bewusst 
schwammig formuliert, um zu demonstrieren, wie leicht man hier den 
Fehler übersehen kann.
Der Compiler ist schon recht schlau. Wenn ich ein Array einbaue, mit 
Größe 31 und das in der Schleife befülle, kommt ja auch sofort eine 
Warnung.
uint8_t test[31];
for (uint8_t i = 0; i < 32; i++) {
   test[i] = 0;
   // ...
}

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
test schrieb:
> Manfred schrieb:
>> Ja, int ist 16 Bit breit, daher ist der Code falsch. Da muss es
>> doch eine Warnung geben...
>
> Da müsste der gcc aber schon sehr clever sein um hier das Problem zu
> sehen.

Der Compiler müsste etwas Code-Analyse betreiben. Wenn man die Zeile
uint32_t mask = 1 << i;
für sich betrachtet, ist da erstmal nichts falsch dran. Eine 1 wird um 
eine variable Anzahl von Bits geschoben. Solange man den Wert von i 
nicht kennt, ist eine Warnung nicht gerechtfertigt. Jetzt ist es an der 
Stelle aber nicht übermäßig schwer für den Compiler, zu wissen, mit 
welchen Werten von i dieser Code definitiv ausgeführt werden wird. Der 
Optimizer analysiert solche Schleifen sowieso, um z.B. loop-unrolling 
betreiben zu können. Von daher könnte er hier schon merken, dass der 
Code definitiv fehlerhaft ist.

> Kann man so etwas heutzutage erwarten?
>
> Ist eigentlich Aufgabe des Programierers derartige Probleme zu erkennen.

Heutzutage ist es aber Aufgabe des Compilers, nicht nur das Programm 
einfach stur in Maschinencode zu übersetzen, wenn das irgendwie geht, 
sondern auch, dem Programmierer zu helfen, Fehler zu vermeiden.
Er übernimmt heute auch die Rolle eines Lint-Tools.

> D.h. wenn man mit Bits rummacht sollte man generell wissen was für
> Datentypen man da benutzt.

Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch 
schnell mal einen Flüchtigkeitsfehler.

Autor: test (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch
> schnell mal einen Flüchtigkeitsfehler.

Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch 
nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab) 
nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-)


Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt 
es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur 
keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in 
Char Arrays gesammelt werden...

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
test schrieb:
> Rolf M. schrieb:
>> Das sollte man. Wie das aber so bei Menschen ist, macht man dabei auch
>> schnell mal einen Flüchtigkeitsfehler.
>
> Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch
> nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab)
> nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-)

Ein uint32_t hat auf jeder Plattform 32-Bit. Ein int/unsigned int hat 
mindestens 16-Bit.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
test schrieb:
> Wobei die Tatsache das ein uint32_t offenbar nur 16bit hat (oder auch
> nicht, hängt bei c offenbar auch von der Mondphase und dem Wochentag ab)
> nicht wirklich hilfreich dabei ist den Überblick zu behalten ;-)

Ich weiß nicht, wie du auf den Quatsch kommst. Das ist jedenfalls 
falsch.

> Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt
> es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur
> keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in
> Char Arrays gesammelt werden...

Sollte unsigned char sein.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
test schrieb:

> Wobei ich da vermutlich auch unfair gegenüber c++ bin, vermutlich gibt
> es geeignete Datentypen und Arten vernünftig zu programmieren. Macht nur
> keiner ;-) Ich meine wenn ich sehe das heutzutage immer noch Bytes in
> Char Arrays gesammelt werden...

Das machen nur C-Programmierer. In C++ nimmt man std::byte.

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MaWin schrieb:
> Das könnte man wahrscheinlich mit ubsan finden.
> 
https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/

Geht das mit bare-metal targets auch (denn im OP ist von avr-gcc die 
Rede)?

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Geht das mit bare-metal targets auch (denn im OP ist von avr-gcc die
> Rede)?

Theoretisch schon.
Ich weiß nicht, ob avr-libc da Unterstützung hat (libubsan).
Vermutlich aber eher nicht.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.