Hallo,
ich bekomme mit dem KEIL Compiler für folgende Codeteile folgende
Fehlermeldung und weiss nicht wie ich diese wegbekomme. kan mir jemand
helfen:
u16 param1= 1300;
if(param1>= 0 && param1<=4095)
{
......
......
......
}
D:\.....\test.c(444): warning: #186-D: pointless comparison of unsigned
integer with zero
/*--------------------------------------------------------------------*/
sprintf((c08*)str_snd_sci_one, "\n\n\c param2=%d\n\0", param2);
D:\.....\test.c(1052): warning: #192-D: unrecognized character escape
sequence
/*--------------------------------------------------------------------*/
Samuel wrote:
> u16 param1= 1300;>> if(param1>= 0 && param1<=4095)> {> ......> ......> ......> }> D:\.....\test.c(444): warning: #186-D: pointless comparison of unsigned> integer with zero
Sinnloser Vergleich einer vorzeichenlosen Zahl mit Null.
param1>= 0 mit param1 als u16 wird immer größer oder gleich 0 sein.
> sprintf((c08*)str_snd_sci_one, "\n\n\c param2=%d\n\0", param2);>> D:\.....\test.c(1052): warning: #192-D: unrecognized character escape> sequence
'\c' gibts nicht.
> if(param1>= 0 && param1<=4095)
if(param1<=4095)
Und was soll "\c" sein? Das abschliessende "\0" ist überflüssig, das
hängt der Compiler sowieso schon dran.
Und ich will mal hoffen, dass "param2" ein Vorzeichen hat, denn sonst
wäre "%d" falsch.
> pointless comparison of unsigned integer with zero
Das mal auf Deutsch übersetzen:
sinnloser Vergleich eines unsigned integer mit 0
Wie lautet deine Zeile?
if(param1>= 0 && param1<=4095)
Aha, der Compiler will dir offenbar mitteilen, dass param1>=0 ein
sinnloser Vergleich ist. Warum?
Welchen Datentyp hat param1? Das ist ein u16, also wohl ein unsigned
int.
Und was ist das Charakteristikum eines unsigned Typen?
Er hat kein Vorzeichen.
Und das bedeutet was?
Er ist per Definition immer positiv, also immer größer oder gleich 0.
Praxisstudent schrieb:> Ich habe gerade das gleiche Problem. leider habe ich meinen Code aus> diesem Artikel:> und es kommt auch der oben beschriebene Fehler. Kann jemand den Artikel> verbessern wenn er so falsch ist?
Aha. Es gibt oben aber keinen Fehler sondern nur zwei Warnings. Und wo
genau schreibst du auch nicht. Schulterzuck
Praxisstudent schrieb:> und beim warning steht dann:> #188-D pointless comparison of unsigned integer with zero
Du hast den falschen Datentyp abgeschrieben. Im obrigen Code ist i ein
int_8 (vorzeichenbehaftet), in deinem Screenshot ist es ein uint_8
(nicht vorzeichenbehaftet).
Praxisstudent schrieb:> Kann jemand den Artikel verbessern wenn er so falsch ist?
Warum sollte es falsch sein, in der Abbruchbedingung ein ">=" stehen zu
haben. Das ist kein Fehler und du bekommst auch keiner FEHLER-Meldung.
Statt "i>=0" könntest du natürlich ein völlig sinnentstellendes "i!=255"
schreiben.
W.A. schrieb:> Statt "i>=0" könntest du natürlich ein völlig sinnentstellendes "i!=255"> schreiben.
Dabei würde sich jeder tot Programmierer augenblicklich im Grab umdrehen
und die lebende Fraktion sich sofort übergeben.
Praxisstudent schrieb:> und beim warning steht dann:> #188-D pointless comparison of unsigned integer with zero
Das gleiche Problem wie im Startpost: Die For-Schleife soll solange
laufen, solange i größer oder gleich 0 ist. Da i aber als Unsigned Int
definiert wird i immer größer oder gleich 0 sein, der Vergleich der
For-Schleife entbehrt jeder Logik. Der Compiler warnt zurecht davor.
Wenn man bis 0 runter zählen will sollte man als Bedingung der
For-Schleife fragen, ob i nicht gleich 0 ist, also:
Moin,
was generelles:
1. Wenn man Integer ohne Vorzeichen mit Kostanten vergleicht, dann
sollte man das immer in der Form tun
if (u8ParamX < 200u)
...
Du teilst dem Compiler mit, dass sowohl die Konstante als auch die
Variable vom gleichen Typ (vorzeichenlos) sind, dann gibt es auch keinen
Ärger.
2. Wenn man eine vorzeichenlose Zahl auf kleiner als 0 vergleicht, dann
ist das wirklich pointless, da die Zahl ja niemals kleiner als Null sein
kann und "größer/gleich Null" ist dann genauso immer wahr... ;)
Beste Grüße
das moeb
PS
Es gibt Leute, die machen das noch etwas anders:
if (200u == u8ParamX)
Vorteil: Wenn man das zweite Gleichheitszeichen vergisst, dann hast du
keine Zuweisung, sondern unkompilierbaren Code...
Nachteil: Man muss bei Vergleichen einmal um die Ecke denken.
M. K. schrieb:> Wenn man bis 0 runter zählen will sollte man als Bedingung der> For-Schleife fragen, ob i nicht gleich 0 ist, also:> uint8_t i;> ...> for( i = 9; i != 0; i--){> //do anything> }> ...
Dann wird der Fall i == 0 aber nicht mehr durchlaufen.
Daher ist das kein gleichwertiger Ersatz zu:
moeb schrieb:> Vorteil: Wenn man das zweite Gleichheitszeichen vergisst, dann hast du> keine Zuweisung, sondern unkompilierbaren Code...
Andersrum wird ein Schuh draus: Wenn man ein Gleichheitszeichen vergisst
hat man in der Bedingung einen Zuweisung und das ist nicht erlaubt,
führt also unausweichlich zum Error.
Frank M. schrieb:> Dann wird der Fall i == 0 aber nicht mehr durchlaufen.
Stimmt, aber das lässt sich anpassen, z. B. so:
M. K. schrieb:> Andersrum wird ein Schuh draus: Wenn man ein Gleichheitszeichen vergisst> hat man in der Bedingung einen Zuweisung und das ist nicht erlaubt,> führt also unausweichlich zum Error.
wer sagt das?
Warum sollte eine Zuweisung nicht erlaubt sein?
M. K. schrieb:> Stimmt, aber das lässt sich anpassen, z. B. so:> int8_t i;>> for( i = 10; i != 0; --i){> //do anything> }
Aber nur, wenn die Laufvariable i innerhalb des Blocks nicht verwendet
wird. Sonst müssen alle Vorkommnisse innerhalb des Blocks von i auf i-1
geändert werden.
Daher ist Dein Vorschlag keine allgemeingültige Alternative ;-)
Peter II schrieb:> M. K. schrieb:>> Andersrum wird ein Schuh draus: Wenn man ein Gleichheitszeichen vergisst>> hat man in der Bedingung einen Zuweisung und das ist nicht erlaubt,>> führt also unausweichlich zum Error.>> wer sagt das?>> Warum sollte eine Zuweisung nicht erlaubt sein?> int i;> if ( i = GetValue() ) {> }>> ist zulässig und auch sinnvoll
Absolut!
Peter II schrieb:> ...>> Warum sollte eine Zuweisung nicht erlaubt sein?>>
1
>inti;
2
>if(i=GetValue()){
3
>}
4
>
>> ist zulässig und auch sinnvoll
OK, ich hatte -Werror an, es wirft bei mir eine Warnung. Warum das aber
Sinnvoll sein soll sehe ich ehrlich gesagt nicht.
Daniel A. schrieb:> Noch einige Varianten:
Hab was am Auge: Wo sind denn da Zuweisungen in der Bedingung? Ich
sehe nur Zuweisungen in der InitialisierungFrank M. schrieb:> Aber nur, wenn die Laufvariable i innerhalb des Blocks nicht verwendet> wird. Sonst müssen alle Vorkommnisse innerhalb des Blocks von i auf i-1> geändert werden.>> Daher ist Dein Vorschlag keine allgemeingültige Alternative ;-)
Hab ich das behauptet, dass es eine allgemeingültige Alternative ist?
Nein, natürlich nicht. Man könnte ja auch einen while-Schleife oder eine
do-while-Schleife benutzen. Und dass man den Schleifenblock anpassen
muss sollte doch auch klar sein. Auch gegangen wäre:
1
uint8_ti;
2
...
3
for(i=9;i!=0;i--){
4
//do anything
5
}
6
//do same as for-loop with i=0
7
...
Man muss es halt so aufbauen, dass es auf das Problem passt, dass man
hat.
Daniel A. schrieb:> for( uint8_t i = 9; ~i; i-- ){
Ahhh, bring unsere Anfänger auf keine falschen Ideen.
Das funktioniert definitiv nicht! Die Abbruchbedingung ist immer false.
Ich lass euch mal Knobeln...
M. K. schrieb:> Peter II schrieb:>> ...>>>> Warum sollte eine Zuweisung nicht erlaubt sein?>>>>> int i;>> if ( i = GetValue() ) {>> }>> >>> ist zulässig und auch sinnvoll>> OK, ich hatte -Werror an, es wirft bei mir eine Warnung. Warum das aber> Sinnvoll sein soll sehe ich ehrlich gesagt nicht.
Falls die aufgerufene Funktion eine Fehlerbehandlung durchführt und im
Fehlerfall Null zurück gibt, dann wäre das legitim. Aber nur bei sehr
guter Kommentierung.
Ein expizites Abfangen von Fehlern würde ich aber in jedem Fall
vorziehen.
Es ging ja um Konstanten.
Ich habe zwar gerade keinen Compiler an, aber:
1
if(200u=GetValue()){}
Sollte definitiv nicht Compilen.
Und die Message war auch: Hier hat man nicht einen fiesen Laufzeitfehler
den man nur durch Debugging irgendwann findet, sondern man wird gleich
in die richtige Zeile gelotzt.
Ähnlich dem ist auch sowas wie:
1
if("".equals(str)){}
In Java, um eine NPE für null-Strings zu verhindern. Daran musste ich
mich aber auch erst gewöhnen.
M. K. schrieb:> OK, ich hatte -Werror an, es wirft bei mir eine Warnung. Warum das aber> Sinnvoll sein soll sehe ich ehrlich gesagt nicht.
Schon einige der ersten Mini-Progrämmchen im Kernighan-Ritchie zeigt,
dass so etwas sogar sehr sinnvoll ist:
1
while((c=getchar())!=EOF)
2
{
3
putchar();
4
}
Bei der Zuweisung in Peters Beispiel konnte der Vergleich (!= EOF)
entfallen, da hier gegen 0 geprüft wurde. Sowas ist das tägliche Brot
des C-Programmierers.
M. K. schrieb:> Hab ich das behauptet, dass es eine allgemeingültige Alternative ist?
Immerhin hast Du danach einen allgemeingültigen Block mit Kommentar "do
anything here" hinterlassen ;-)
Aber selbst wenn er nicht allgemeingültig gedacht war: Gehen wir nochmal
auf das Programm von Praxisstudent zurück:
Im for-Block steht da
1
string[i]=....
und von daher ist Dein Vorschlag auch nicht gültig.
Btw: Du hattest sowieso int8_t verwendet. Da muss an den Parametern für
for() genau gar nichts geändert werden.
Student schrieb:> Also das stimmt ja nicht so ganz:int i;> if ( i = GetValue() ) {> }>> Es ging ja um Konstanten.> Ich habe zwar gerade keinen Compiler an, aber:if (200u = GetValue()) {}>> Sollte definitiv nicht Compilen.> Und die Message war auch: Hier hat man nicht einen fiesen Laufzeitfehler> den man nur durch Debugging irgendwann findet, sondern man wird gleich> in die richtige Zeile gelotzt.
Ja, du hast Recht. Wir haben ein wenig aneinandervorbeidiskutiert ;)
Frank M. schrieb:> Schon einige der ersten Mini-Progrämmchen im Kernighan-Ritchie zeigt,> dass so etwas sogar sehr sinnvoll ist: while ((c = getchar ()) != EOF)> {> putchar ();> }
Das ist keine Zuweisung in der Bedingung. Die Bedingung lautet hier
nämlich:
1
c!=EOF
zuvor wird die Anweisung
1
c=getchar()
ausgeführt.
Frank M. schrieb:> und von daher ist Dein Vorschlag auch nicht gültig.
Und wo habe ich geschrieben, dass das eine fertig Lösung für das Problem
ist? Ich hab echt was am Auge, gehe gleich mal zum Arzt.
Frank M. schrieb:> Du hattest sowieso int8_t verwendet.
Nur weil ich deinen Beitrag kopiert hatte. Schau noch mal in meinen
Vorschlag genau rein, und zwar den ersten den du bemängelt hast. ;)
M. K. schrieb:> Das ist keine Zuweisung in der Bedingung.
Doch.
Genauso, wie Peters
1
if(i=GetValue()){
eine Zuweisung in der Bedingung ist. Um die Compiler-Warnings
wegzubekommen, muss Peter die Zeile nur richtig ausschreiben:
1
if((i=GetValue())!=0){
Dann ist die Warnung weg. Aber beide Formulierungen sind absolut
äquivalent, die von Peter ist lediglich eine Abkürzende Schreibweise, wo
aber der Compiler nicht mehr sicher sein kann, dass Peter sich
verschrieben hat mit dem einfachen Gleichheitszeichen. Daher die
Warnung.
Und wenn Du nun schaust, sieht
Klaus H. schrieb:> Daniel A. schrieb:>> for( uint8_t i = 9; ~i; i-- ){>> Ahhh, bring unsere Anfänger auf keine falschen Ideen.> Das funktioniert definitiv nicht! Die Abbruchbedingung ist immer false.>> Ich lass euch mal Knobeln...
Ach ja, die Integer promotion, hatte ich vergessen...