Forum: Compiler & IDEs for-Funktion Datentypen


von Tobias P. (Gast)


Lesenswert?

Wenn ich in meinem Code eine Variable als unsigned int oder uint8_t
definieren bekomme ich bei jeder for-funktion immer folgende
Fehlermeldung:

warning: comparsion is always true due to limited range of data types

Meine for-funktion sieht folgendermaßen aus:

for (t=wait;t>=0;t--)
{
//führe code in for-schleife aus
}

Irgendjemand eine Idee woran das liegen kann?

von Rufus T. Firefly (Gast)


Lesenswert?

Eine Variable vom Typ "unsigned irgendwas" kann nicht negativ werden.
Der Vergleich

   variable >= 0

ist somit immer wahr.

von Peter Dannegger (Gast)


Lesenswert?

"Irgendjemand eine Idee woran das liegen kann?"

Geh nochmal zurück in die erste Klasse:

Natürliche Zahlen (unsigned) sind immer >= 0.


Peter

von Tobias P. (Gast)


Lesenswert?

Upps, mein Fehler !
Aber so müsste es doch gehen.
Zumindest bekomme ich keine Fehlermeldung mehr.

for (t=wait;t|=0;t--)
{
//führe code in for-schleife aus
}

von OldBug (Gast)


Lesenswert?

...vermutlich willst Du das:

for(t = wait; t > 0; t--);
{
  /* code... */
}

?

von Chris (Gast)


Lesenswert?

> Aber so müsste es doch gehen.

Ob das so geht kannst du in wenigen Minuten selbst, evlt. mit Hilfe
eines Debuggers, herausfinden.

Interessanterweise sollte das tatsächlich funktionieren, wenn auch eine
unübliche Lösung. Aber bitte tu dir den Gefallen und lies das Kapitel
über for-Schleifen und das über Vergleichsoperatoren in deinem C-Buch
nochmal genau durch, damit du verstehst, wieso das funktioniert. :)

von Tobi (Gast)


Lesenswert?

for(t = wait; t; t--);
{
  /* code... */
}

ist Code-sparender als z.B.

for(t = 0; t < wait; t++);
{
  /* code... */
}

und somit schon üblich.

von Tobi (Gast)


Lesenswert?

SORRY!! Ohne die ";" SCH... Kopiererei.

for(t = wait; t; t--)
{
  /* code... */
}

ist Code-sparender als z.B.

for(t = 0; t < wait; t++)
{
  /* code... */
}

und somit schon üblich.

von Chris (Gast)


Lesenswert?

> und somit schon üblich.

Auf diese Weise natürlich (wobei ich vermutlich "t != 0" in die
Bedingung schreiben würde, für den Compiler ist das das gleiche).

Aber schau dir nochmal genau die Version von Tobias an:
> for (t=wait;t|=0;t--)
Du wirst wohl nicht bestreiten, dass "t |= 0" als Bedingung ein wenig
unüblich und nicht gerade sehr intuitiv ist.

von Tobi (Gast)


Lesenswert?

Oh, t|=0 als Bedingung geht zwar ist aber schon seltsam.
Ich hab wohl t!=0 gelesen....

von Tobias P. (Gast)


Lesenswert?

Also ist wohl:

for(t = 0 ; t < wait ; t++)
{
}

die Lösung, die am Besten ist und am wenigsten Speicher benötigt.
Oder ?

von Chris (Gast)


Lesenswert?

Nein, Tobis Variante ist potentiell platzsparender:
for(t = wait; t; t--)
{
  /* code... */
}

Ein Test auf 0 ist je nach Architektur schneller als ein Test auf einen
bestimmten Wert.
Allerdings bezweifle ich beinahe, dass das im fertigen Programm
signifikante (=messbare) Auswirkungen hat.

von Chris (Gast)


Lesenswert?

Nachtrag: Die Schleifen unterscheiden sich allerdings ein wenig,
abgesehen von der Laufrichtung. Bei deiner Variante nimmt t niemals den
Wert wait an, dafür ist es beim ersten Durchlauf 0. Bei der
platzsparenderen Variante wird t niemals 0 und ist beim ersten
Durchlauf gleich wait.

von Tobias P. (Gast)


Lesenswert?

Also welche Variante ist jetzt potentiell besser ?


for(t = wait; t; t--)
{
}

oder:

for(t = 0 ; t < wait ; t++)
{
}

von OldBug (Gast)


Lesenswert?

Mal so ganz nebenbei: wie ist 't' definiert?

von OldBug (Gast)


Lesenswert?

Zyklen zählen darfst Du selber ;)

--8<--
  for (t = wait; t; t--)
  d2:  80 91 00 01   lds  r24, 0x0100
  d6:  90 91 01 01   lds  r25, 0x0101
  da:  90 93 03 01   sts  0x0103, r25
  de:  80 93 02 01   sts  0x0102, r24
  e2:  80 91 02 01   lds  r24, 0x0102
  e6:  90 91 03 01   lds  r25, 0x0103
  ea:  89 2b         or  r24, r25
  ec:  31 f0         breq  .+12       ; 0xfa
  ee:  80 91 02 01   lds  r24, 0x0102
  f2:  90 91 03 01   lds  r25, 0x0103
  f6:  01 97         sbiw  r24, 0x01  ; 1
  f8:  f0 cf         rjmp  .-32       ; 0xda
    ;

  for (t = 0; t <= wait; t++)
  fa:  10 92 03 01   sts  0x0103, r1
  fe:  10 92 02 01   sts  0x0102, r1
 102:  20 91 02 01   lds  r18, 0x0102
 106:  30 91 03 01   lds  r19, 0x0103
 10a:  80 91 00 01   lds  r24, 0x0100
 10e:  90 91 01 01   lds  r25, 0x0101
 112:  82 17         cp  r24, r18
 114:  93 07         cpc  r25, r19
 116:  50 f0         brcs  .+20       ; 0x12c
 118:  80 91 02 01   lds  r24, 0x0102
 11c:  90 91 03 01   lds  r25, 0x0103
 120:  01 96         adiw  r24, 0x01  ; 1
 122:  90 93 03 01   sts  0x0103, r25
 126:  80 93 02 01   sts  0x0102, r24
 12a:  eb cf         rjmp  .-42       ; 0x102
    ;
-->8--

von Tobias P. (Gast)


Lesenswert?

t ist uint8_t
Steht aber auch ganz am Anfang.

Von Assembler hab ich keine Ahnung, deswegen weiß ich auch nicht was
ich dort zählen soll.

von OldBug (Gast)


Lesenswert?

Ich habe sicherheitshalber nachgefragt, denn:

Ist 't' nur uint8_t, dann kannst Du Dir die ganze for-Schleife
sparen, die wird ziemlich sicher wegoptimiert. Der Code, der in der
Schleife ausgeführt wird könnte noch Einfluss darauf haben, aber das
ist nach Deinen bisherigen Auskünften unwahrscheinlich.

Wenn Du wissen willst, welche Variante performanter ist, dann musst Du
Dich schon damit auseinandersetzen, wie viele Zyklen die jeweiligen
Assembleranweisungen zur Ausführung benötigen. Ich bin da grad zu faul
zu...

von Tobi (Gast)


Lesenswert?

Probiers mal aus!

Kompilier beide Varianten und schau nach, wieviel Code rauskommt.
Das steht im Output Fenster unten am Bildschirm, wenn du im
Programers' Notepad programmierst:

Device: atmega32

Program:   10464 bytes (31.9% Full)
(.text + .data + .bootloader)

Data:        324 bytes (15.8% Full)
(.data + .bss + .noinit)



c:\avr\atmega_projects\mainboard_tester>pause
Drcken Sie eine beliebige Taste . . .

von Tobias P. (Gast)


Lesenswert?

Habs mal gerade ausprobiert:

for (t=x;t;t--)

AVR Memory Usage:
Device: at90s2323

Program:
1362 bytes (66.5% Full)
(.text + .data + .bootloader)

Data:
0 bytes (0.0% Full)
(.data + .bss + .noinit)


for (t=0;t<=x;t++)

AVR Memory Usage:
Device: at90s2323

Program:
1422 bytes (69.4% Full)
(.text + .data + .bootloader)

Data:
0 bytes (0.0% Full)
(.data + .bss + .noinit)

von A.K. (Gast)


Lesenswert?

"Also welche Variante ist jetzt potentiell besser ?"

Im Prinzip stimmen die Kommentare oben zwar schon, aber es hängt auch
arg vom Compiler ab. Wenn t in der Schleife nicht verwendet wird, dann
ist beispielsweise bei GCC der Code der Schleife identisch. Weil der
diese klassische Kontrollstruktur identifiziert und optimiert:
.L5:
  ..for-body..
  sbiw r28,1
  brne .L5

Und wenn's drauf ankommt: Gilt wait > 0, dann ist
      t = wait; do ... while (--t != 0);
etwas kürzer als jede for-Variante.

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.