Forum: Compiler & IDEs GCC Warnugen beheben...


von Markus Boremski (Gast)


Lesenswert?

Hallo ihr coder

Ich arbeite mich seit ein paar wochen in C ein und stelle fest das mein
code verdammt viele Warnungen generiert.

Hatte schnell festgestellt dass die es trotzdem läuft. Jetzt wollte ich
aber gerne die Warnungen aus meinem Code enfernen oder vielleicht
wenigstens abschalten.

Grund: wenn ich denn dann mal wieder einen error produziert habe so
muss ich mich erst durch mindestens 12.437 Zeilen Warungen wühlen um
den eigendlichen Error zu finden.


Hier eine Hitlist der häufigsten Warnungen:

unübertroffen auf Platz 1:
warning: passing arg 1 of `sprintf' discards qualifiers from pointer
target type
Code in dieser Zeile: sprintf(text, "   Helligkeit:  ");

wird dicht gefolgt von diesem hier (Platz 2):
warning: assignment discards qualifiers from pointer target type
Code in dieser Zeile: (switch usw davor) case 0  : ptr = p_textV24;tmp2
 = V_24;break;

dann etwas abgeschlagen auf Platz 3:
warning: assignment makes integer from pointer without a cast
Code hier: if (sp[0x01] < 63) TempPos = " ";

und dann nur einmal folgendes:
warning: return type of 'main' is not `int'

Würde mich freuen was von euch zu hören

LG Markus

von Rolf Magnus (Gast)


Lesenswert?

> Ich arbeite mich seit ein paar wochen in C ein und stelle fest das
> mein code verdammt viele Warnungen generiert. Hatte schnell
> festgestellt dass die es trotzdem läuft. Jetzt wollte ich aber
> gerne die Warnungen aus meinem Code enfernen

Gute Idee.

> oder vielleicht wenigstens abschalten.

Das bitte nur, wenn du wirklich verstehst, was die Warnung bedeutet und
sicher weißt, daß sie harmos ist.

> warning: passing arg 1 of `sprintf' discards qualifiers from
> pointer target type >Code in dieser Zeile: sprintf(text, "
> Helligkeit:  ");

Ohne Angabe der Argumenttypen kann man nur mutmaßen. Ist text
vielleicht ein Zeiger auf const char oder volatile char?

> warning: assignment discards qualifiers from pointer target type
> Code in dieser Zeile: (switch usw davor)
> case 0  : ptr = p_textV24;tmp2  = V_24;break;

Hier stimmen vermutlich die Zeigertypen auch nicht.

> warning: assignment makes integer from pointer without a cast
> Code hier: if (sp[0x01] < 63) TempPos = " ";

Sieht so aus als sei TempPos ein int. Warum benutzt du einen int, um
die Adresse des Strings drin zu speichern? Dazu sind Zeiger da.

> warning: return type of 'main' is not `int'

Was ist daran unklar? Die C-Norm schreibt vor, daß main als Rückgabetyp
int haben muß. Das hat die Funktion bei dir vermutlich nicht. Zugegeben,
bei einem Mikrocontroller ist das recht nutzlos, aber es ist eben so in
C. Schaden tut es ja auch nicht, also gib einen int zurück.

von Daniel B. (khani)


Lesenswert?

Hallo Markus,

warnings sind der Aufruf des Compilers zur Überprüfung des
Sourcecodes.

Falls eine Warnung auftritt heißt das meist, dass warhscheinlich das
Richtige (also das, was Du gewollt hast) gemacht wird. Warnings deuten
aber auch meist auf unsauberen Code hin. An diesen Stellen sollte man
dann entsprechende Casts oder andere Codeformulierungen verwenden, um
das Ganze besser zu gestalten.

Also warnings nicht ausschalten, lieber dementsprechend mehr im
Sourcecode formulieren - das bedeutet i.A. nicht, dass am Ende das
Kompilat größer wird.

Beispiel :
1
uint16_t ui16Dummy = 0x0000;
2
uint8_t pui8Dummy;
3
4
pui8Dummy = ui16Dummy;
führt wahrscheinlich dazu, dass der Compiler eine Warnung abgibt, weil
eine Adresse von unit16_t in einen Pointer kopiert wird. Besser ist da
1
uint16_t ui16Dummy = 0x0000;
2
uint8_t pui8Dummy;
3
4
pui8Dummy = (uint8_t *)ui16Dummy;

Das kompiliert nicht größer, jetzt weiß der Compiler aber genau, dass
das was Du geschrieben hast auch dem entspricht, was Du gemeint hast.

MfG, Daniel
MfG, Daniel.

von Peter Dannegger (Gast)


Lesenswert?

> warning: return type of 'main' is not `int'

Beim AVR-GCC darf im main kein return stehen !

Es wird nämlich zu Beginn des main der Stackpointer neu gesetzt und
damit kann das main nirgends hin zurückkehren.

Laut ANSI-C ist main eine ganz normale Funktion, und kann sich daher
auch selbst aufrufen. Aber das geht eben nicht im AVR-GCC !!!

Das main muß also eine Endlosschleife ohne return beinhalten, dann wird
nicht mehr gemeckert.



Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Beim AVR-GCC darf im main kein return stehen !

Quark.

> Es wird nämlich zu Beginn des main der Stackpointer neu gesetzt und
> damit kann das main nirgends hin zurückkehren.

Doch.  Das return von main() ist ja offziell eine Übergabe des
Rückkehrwerts an die Funktion exit().  Der AVR-GCC weiß um seine
Besonderheit des main(), und implementiert diese als Sprung in die
Funktion exit().

Das Ganze hat natürlich nur dann einen Effekt, wenn man ein eigenes
exit() vorsieht.  Außerdem sollte exit() natürlich nirgendwohin
zurückkehren wollen. ;-)

> Laut ANSI-C ist main eine ganz normale Funktion, und kann sich daher
> auch selbst aufrufen. Aber das geht eben nicht im AVR-GCC !!!

Kein Grund zum Rumschreien.

Das Einzige, was nicht funktioniert ist, dass man main() rekursiv
aufruft.  Aber ehrlich, wo hast du das im Realen Leben[tm] schon mal
gesehen, dass jemand main() rekursiv aufruft?  Ich kenne das
bestenfalls vom IOCCC.

Ganz davon abgesehen, ich glaube, die Umwandlung von main() in eine
,,ganz normale'' Funktion steht bei irgendeinem AVR-GCC-Entwickler
sogar auf der Liste.

> Das main muß also eine Endlosschleife ohne return beinhalten, dann
> wird nicht mehr gemeckert.

Es wird auch nicht gemeckert, wenn man das return dranschreibt, und
falls davon eine Endlosschleife ist, erkennt der Optimizer das auch
und eliminiert das return.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

p.s.:

> Laut ANSI-C ist main eine ganz normale Funktion, ...

Ist es übrigens nicht.  Erstens ist der Prototyp vorgeschrieben,
außerdem (das macht GCC übrigens nicht) soll beim Erreichen von
} in main() eine 0 zurückgegeben werden.  Nur zwei Beispiele, warum
das keine ,,ganz normale'' Funktion sein kann.

von Rolf Magnus (Gast)


Lesenswert?

> Erstens ist der Prototyp vorgeschrieben,

Und? Trotzdem ist es eine ganz normale Funktion.

> außerdem (das macht GCC übrigens nicht) soll beim Erreichen von
> } in main() eine 0 zurückgegeben werden.

Nur dann, wenn da auch ein "return 0;" steht. Du verwechselst es
evtl. mit C++.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

>> außerdem (das macht GCC übrigens nicht) soll beim Erreichen von
>> } in main() eine 0 zurückgegeben werden.

> Nur dann, wenn da auch ein "return 0;" steht. Du verwechselst es
> evtl. mit C++.

Nein.  ISO/IEC 9899:1999:

``5.1.2.2.3 Program termination

1 If the return type of the main function is a type compatible with
  int, a return from the initial call to the main function is
  equivalent to calling the exit function with the value returned by
  the main function as its argument; reaching the } that terminates
  the main function returns a value of 0. [...]''

von Benedikt (Gast)


Lesenswert?

>Das main muß also eine Endlosschleife ohne return beinhalten, dann wird
nicht mehr gemeckert.

Muss nicht:
In der WinAVR Anleitung steht, dass am Ende von main automatisch eine
Endlosschleife eingebaut ist.
Schreibt man also in ein Programm return, hat das diesselbe Wirkung wie
eine Endlosschleife.

von Peter D. (peda)


Lesenswert?

@Benedikt

"Schreibt man also in ein Programm return, hat das diesselbe Wirkung
wie eine Endlosschleife."


???

Also ehe ich ständig nachsehe, welche Extrasüppchen jeder einzelne
Compiler kocht, schreib ich es doch lieber so hin, daß es portabel ist,
also jeder Compiler es versteht.

Bei einem "return" erwarte ich eigentlich, daß die Funktion immmer
zum Aufrufer zurückkehrt und nicht irgendwelche Sperenzchen macht.

Wenn das Main am Schluß steht, kann das Programm durch die leeren
0xFFFFs durchnudeln, bis es wieder bei 0x0000 ankommt, d.h. es sieht
nur so aus, als ob eine Schleife gemacht wird.

In der Regel beinhaltet aber das Main 2 Teile:

1. alle Initialisierungen (LCD, UART usw.)
2. die zyklische Abarbeitung aller Hauptprozesse

Und das geht nur, wenn man explizit eine Hauptschleife hinschreibt.
Wie sonst soll denn der Compiler erkennen, was einmalig und was
zyklisch auszuführen ist ?


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Bei einem "return" erwarte ich eigentlich, daß die Funktion immmer
> zum Aufrufer zurückkehrt und nicht irgendwelche Sperenzchen macht.

Genau das macht es doch.  Zumindest das Äquivalent davon...  Wer ist
aber bitte der Aufrufer von main()?  (Von rekursiven Aufrufen
abgesehen, wie schon geschrieben, daran wird auch noch gearbeitet,
aber das ist auch alles andere als wirklich ein wichtiges Feature.)

Wenn main() zurückkehrt, wird halt ein exit() aufgerufen.  Genau das
schreibt der C-Standard vor, und genau das macht der Compiler.  Das
exit() macht dann per default eine Endlosschleife, aber du kannst dir
dafür auch gern was anderes einfallen lassen.

Eine vernünftige Applikation hat natürlich trotzdem ihre eigene
Hauptschleife, keine Frage (und wenn der Compiler feststellt, dass das
main() gar nicht zurückkehren kann, kann er sich auch das
Weiterreichen an exit() sparen).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.