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
> 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.
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_tui16Dummy=0x0000;
2
uint8_tpui8Dummy;
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_tui16Dummy=0x0000;
2
uint8_tpui8Dummy;
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.
> 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
> 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.
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.
> 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++.
>> 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. [...]''
>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.
@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
> 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).