PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : comparison is always true



tholan
04.01.2009, 19:00
Hallo und frohes Neues!
Warum führt Folgendes:


uint8_t count;
for (count=0; count<=255; count++) {}

..immer zu dieser Warnung:

lcd.c:84: warning: comparison is always true due to limited range of data type
Muß ich in einer 8Bit MCU eine 16Bit Variable deklarieren, um den 8Bit
Wertebereich nutzen zu können?
Funktioniern tuts ja wie ich möchte, nur wurmt mich diese Warnung doch ein bischen.
thx,
tholan

McJenso
04.01.2009, 19:19
Hallo,


wie müsste count den aussehen, um nicht <= 255 zu sein?

Gruß

Jens

tholan
04.01.2009, 20:05
Das:
< 255
... gibt keine Warnung, aber dann zählts nur bis 254 => 0xfe.
Für mich ist die Frage, wie der Vergleichsoperator sein muß,
wenn ich den vollen Wertebereich ohne Compilerwarnung nutzen möchte.

markusj
04.01.2009, 20:19
Die Sache ist ganz einfach: Das Byte KANN nur <= 255 sein.
Dementsprechend wird das ganze immer Wahr sein.
Du willst ja den Übergang von 255 auf 0 erkennen, wenn ich mich nicht irre, hat der AVR ein entsprechendes Flag dafür.
Evtl. könntest du also prüfen, ob der Null-Flag in SREG gesetzt ist.

mfG
Markus

tholan
04.01.2009, 21:40
Das ich in einem Byte nur bis 255 zählen kann, ist mir schon klar,
warum aber die Warnung?
Ist das ein Bug im Compiler?
Die Warnung würde Sinn machen, wenn der Compiler erst addieren ließe und der Atmel
dann überprüft, ob die Bedingung noch wahr ist,
wobei er das nicht müßte, da ich ja sowieso will, daß er nur bis 255 zählt?????

Duke of Doom
04.01.2009, 21:48
Nein.... der Compiler hat recht mit seiner Warnung.

Wie markusj schon sagte, die einzige Möglichkeit dass der Ausdruck in der for-Schleife false wird, ist wenn count größer als 255 wird. Das ist aber nicht möglich da der Datentyp den du verwendest eben nur werte bis 255 speichern kann.

tholan
04.01.2009, 21:58
Dann darf ich das also als Warnung an den dummen Programmierer werten,
daß er auf seinen Wertebereich aufpassen soll, weil er so knapp an die Bereichsgrenze ranzählt?
Dann kann man die Warnung also links liegen lassen.

sternst
04.01.2009, 22:03
Dann kann man die Warnung also links liegen lassen.
Du hast offensichtlich immer noch nicht realisiert, dass du da eine Endlosschleife programmiert hast.
Der Vergleich ist (wie der Compiler dir sagt) immer wahr, also wird die Schleife nie beendet.

tholan
04.01.2009, 22:19
Falsch,
sie zählt brav von 0 bis 255 und beendet sich dann,
die Zahlen werden währenddessen in 3 dezimale Digits zerlegt und auf meinem LCDisplay zur Anzeige gebracht, wie es sein soll.
Ich habe nur eine unnötige Warnung.

McJenso
04.01.2009, 22:30
Hallo,

kannst du den relevanten Code mal komplett posten. Die Schleife kann so wie oben dargestellt nicht beendet werden. Da muss es noch etwas anderes geben.

Gruß

Jens

sternst
04.01.2009, 22:32
Falsch,
sie zählt brav von 0 bis 255 und beendet sich dann
Die Schleife oben garantiert nicht.

tholan
04.01.2009, 22:43
Der Wert 255 entspricht dem binären Wert 11111111.
der paßt Augenscheinlich in 8 Bit!!!
Die Bedingung <=255 ist natürlich immer wahr für den angegebenen Zählbereich.
Sonst würds nicht zählen.
@sternst: Hast Du deinen Mikro denn schonmal bis 255 zählen lassen?
Wahrscheinlich nehmt ihr wohl alle immer uint32 für son' armen 8 Bitter?
Das das mit uint8_t funktioniert, sehe ich an meinem Display.

MSN
04.01.2009, 22:44
doch die schleife oben läuft!sie zählt nämlich bis count<=(GLEICH)255 is
deshalb is das ganze bei 255 zuende!

radbruch
04.01.2009, 22:47
Falsch,
sie zählt brav von 0 bis 255 und beendet sich dann...Na, das kann ich aber auch nicht glauben. Ein Byte ist immer kleinergleich 255, für mehr fehlt ihm leider ein Bit ;)


die Zahlen werden währenddessen in 3 dezimale Digits zerlegt und auf meinem LCDisplay zur Anzeige gebracht, wie es sein soll.
Wenn du natürlich die Schleife endlos ausführst wirst du nicht bemerken das sie nach dem ersten Aufruf nicht beendet wird.

MSN
04.01.2009, 22:50
was mir gerade noch einfällt: vlt findet ein impliziter typecast statt?

tholan
04.01.2009, 22:52
Tjaaa, ist halt nur die unnötige Warnung... :)
??

sternst
04.01.2009, 22:57
doch die schleife oben läuft!sie zählt nämlich bis count<=(GLEICH)255 is
deshalb is das ganze bei 255 zuende!

Oh mein Gott.
Die Schleife läuft solange count<=255 ist, nicht bis.
Es ist und bleibt eine Endlosschleife, da gibt es nichts dran zu rütteln.

tholan
04.01.2009, 23:01
Oh Mann
ich hab hinter die for-Schleife extra noch ein paar Buchstaben aufs Display geschrieben,
muß ich jetzt ein .avi machen?
Wenn ich den Code poste, dann glaubt Ihr doch nicht, daß es pfundst?

MSN
04.01.2009, 23:10
doch die schleife oben läuft!sie zählt nämlich bis count<=(GLEICH)255 is
deshalb is das ganze bei 255 zuende!

Oh mein Gott.
Die Schleife läuft solange count<=255 ist, nicht bis.
Es ist und bleibt eine Endlosschleife, da gibt es nichts dran zu rütteln.
jap hast recht is mir auch aufgefallen bin heut morgen erst spät nach hause gekommen und nen bisschen verpennt sry

sternst
04.01.2009, 23:14
Wenn ich den Code poste, dann glaubt Ihr doch nicht, daß es pfundst?
C ist keine Frage von "Glauben", sondern von Regeln und Standards.
Die von dir oben gepostete Schleife ist eindeutig eine Endlosschleife, da ist kein Spielraum für andere Interpretationen.
Wenn sie sich bei dir anders verhält, dann weicht der tatsächliche Code (poste ihn doch endlich mal) vom obigen ab (z.B "manuelles" Verlassen der Schleife durch ein break), oder es ist ein Compiler-Bug.

radbruch
04.01.2009, 23:21
...da ist kein Spielraum für andere Interpretationen.
Ist leider doch. Wir wissen nicht wie sein uint8_t definiert ist...

(..aber das ist eher theoretisch..)

sternst
04.01.2009, 23:25
...da ist kein Spielraum für andere Interpretationen.
Ist leider doch. Wir wissen nicht wie sein uint8_t definiert ist...
Doch, wissen wir. Durch die Warnung, denn die orientiert sich natürlich am tatsächlichen Datentyp, und nicht am Typ-Bezeichner.
Dass bei ihm ein uint8_t versehentlich größer ist als 8 Bit, scheidet als Möglichkeit daher aus.

tholan
05.01.2009, 00:03
](*,)
Nun ja,
Knieschuß is auchn Treffer?
Ihr habt Recht!
Das lief alles in einer "while(1){}" Schleife.
D.h. die ist wahrscheinlich garnicht zum Zuge gekommen,
da die for Schleife nie beendet wurde.
Ich hatte halt zum Test die Schleife auf <=254 gesetzt und dann noch ein paar Buchstaben
in der while Schleife zur Ausgabe gebracht,
dabei allerdings vergessen, die Schleife wieder zum Testen auf <=255 zu setzen.
Ist mir wirklich unangenehm.
'Tschuldigung.

Gibts denn einen Vergleichsoperator, mit dem ich den vollen Wertebereich
zum Zählen nutzen kann?
==255 ist doch auch Quatsch?

p.s.
Hab mir den Thread nochmal durchgelesen, bin noch ein bischen kleiner geworden
und der Groschen ist laangsam gefallen:
C ist schon vertrakter als Basic.
Es wird also solange addiert, wie <= 255 wahr ist, also auch bei 255.
und das ganze wird dann dank Überlauf zu 0 und wieder wahr.
Was mich nach dieser Logik dann wundert ist, daß <255 halt nur bis 254 geht.
Wenn 254 wahr ist, dann müßte doch auch noch eins addiert werden.
Tuts aber nicht, wenn ich nicht schon wieder geschielt habe.

markusj
05.01.2009, 01:19
Wie ich schon in meinem ersten Post geschrieben habe, hat jeder (?) AVR ein sogenanntes Register SREG.
Darin gibt es einen Flag, der dir anzeigt, ob das Ergebnis der letzten Operation Null ist.
Wobei ich noch nie mit diesen Flags direkt gearbeitet habe, demensprechend kann ich dir nicht sagen, ob das ganze funktioniert. Außerdem müsstest du dann den ersten Schleifendurchlauf abfangen.
Am einfachsten ist es vermutlich, 254 durchläufe zu machen und dann den Code nochmal hintendran zu kopieren (auch wenn mir der Gedanke wehtut).
Evtl. hat jemand noch ne bessere Idee.

mfG
Markus

Jaecko
05.01.2009, 01:56
Warum nicht einfach ne ui16_t als Zählvariable? Das eine Byte mehr sollte im Speicher ja noch Platz haben.

sternst
05.01.2009, 02:42
Was mich nach dieser Logik dann wundert ist, daß <255 halt nur bis 254 geht.
Wenn 254 wahr ist, dann müßte doch auch noch eins addiert werden.
Tuts aber nicht, wenn ich nicht schon wieder geschielt habe.
Doch, wird es. Da aber 255 die Bedingung nicht mehr erfüllt, wird mit dieser 255 der Inhalt der For-Schleife nicht mehr ausgeführt.
Wenn du aber hinter der For-Schleife count testest, wird es dort 255 sein.

Die Lösung deines Problems:

uint8_t count = 0;
do {
// tue etwas mit count von 0 - 255
} while (++count);

tholan
05.01.2009, 03:46
Doch, wird es. Da aber 255 die Bedingung nicht mehr erfüllt, wird mit dieser 255 der Inhalt der For-Schleife nicht mehr ausgeführt.
Wenn du aber hinter der For-Schleife count testest, wird es dort 255 sein.
Also dieses C hat sich doch bestimmt mal ein Professor auf Pille ausgedacht :) .
Irgendwie hats ja ne Logik. Da muß man aber erstmal drauf kommen.
Ich glaub ich habs kapiert!
Morgen, ähh Heute werd ichs in meinen Mega16 füttern.
Habt vielen Dank,
tholan

markusj
05.01.2009, 12:19
Warum nicht einfach ne ui16_t als Zählvariable? Das eine Byte mehr sollte im Speicher ja noch Platz haben.
Weil 16-Bit Rechenoperationen mehr RAM und Rechenzeit brauchen.

@tholan: Das ist in den meisten Programmiersprachen so. Und wenn du dir mal in irgend einem C-Buch eine ein Ablaufdiagramm der for-Schleife gesehen hast, stellst du fest, dass eben erst inkrementiert wird und dann geprüft.

Die Lösung von sternst ist tatsächlich die schönste (warum bin ich da eigentlich nicht drauf gekommen???)

mfG
Markus

thewulf00
05.01.2009, 14:32
Warum nicht einfach ne ui16_t als Zählvariable? Das eine Byte mehr sollte im Speicher ja noch Platz haben.
Weil 16-Bit Rechenoperationen mehr RAM und Rechenzeit brauchen.
Nur unwesentlich.
Im ASM sinds nur ein paar Anweisungen mehr.


Sternst hat die von Dir gesuchte Lösung bereits gepostet. Und das ist nicht die "schönste" Lösung, sondern die logische Alternative.
Eine Fußschleife und keine Kopfschleife ist hier Deines Problems Lösung.

tholan
05.01.2009, 22:41
Na, ich resümier nochmal:
Was nicht in meinen Schädel wollte, ist, daß auf "true" getestet wird.
Ich hab so intuitiv immer mit mir rumgeschleppt, daß in einer Schleife auf
"false" getestet wird, bis "true" oder
"gleich" erreicht wird, um die Abbruchbedingung zu liefern.
Wenn man auf "true" testet, hat man logischerweise dieses Problem,
da mindestens ein Element "false" sein muß um den Abbruch zu gewährleisten.
Warum die "do while" Schleife funktioniert, sie fängt immerhin mit ner "falschen" Null an,
frag ich nicht, weil ichs schon gefunden habe :) .
Beim ersten Durchlauf wird hier wohl vor der ersten Addition nicht auf Wahrheit überprüft
und somit rutscht die erste "0" mit durch, ohne die Schleife abzubrechen.
Ob das nun schön ist, beurteile ich als Anfänger garnicht.
Auf jeden Fall würde ich C nicht unbedingt "intuitiv" nennen.
Ich hab ehrlich gesagt auch noch nicht probiert, was Bascom macht
bei: "FOR N=0 TO 255" mit "DIM N AS BYTE" ..oder so.
Der Thread war für mich wirklich sehr lehrreich.
Ich muß mir mal ein gutes C Buch zulegen.
thx,
tholan

sternst
05.01.2009, 23:04
Beim ersten Durchlauf wird hier wohl vor der ersten Addition nicht auf Wahrheit überprüft und somit rutscht die erste "0" mit durch, ohne die Schleife abzubrechen.

Das klingt ja fast so, als ob du hier irgendein Fehlverhalten witterst. Dabei macht der Compiler nur, was ich ihm im Sourcecode mitgeteilt habe:
while (++count)
Beachte hierbei, dass das ++ vorne an count steht. Das bedeutet "erhöhe count erst um Eins und teste danach auf True".

Du scheinst auch zu denken, die Addition sei integraler Bestandteil der Schleife (in der Basic-For-Schleife ist sie das auch), dem ist aber nicht so. Man könnte das ganze auch etwas "ausführlicher" schreiben, dann wird der Ablauf für dich vielleicht etwas klarer:

uint8_t count = 0;
do {
// etwas tun
count = count + 1;
} while (count != 0);

tholan
05.01.2009, 23:32
pühh..
also noch genauer hingucken.
Vielen Dank für Deine Geduld mit mir!