Frage

ich mich gefragt, ob es eine saubere Art und Weise ist von 0 bis 255 zu zählen einen 8-Bit-Datentyp verwenden, so etwas wie:

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

Dies wird sich natürlich nicht funktionieren, aber es macht es klar, dass man von 0 bis 255 zählen möchten

Eine Arbeitslösung wäre so etwas wie:

uint8_t i(0);
do
{
    ...
    ++i;
}
while(i > 0);

Aber hier ist es nicht klar, es zählt von 0 bis 255.

Dies funktioniert auch, aber es ist einfach hässlich IMHO:

uint8_t i(0);
while(true)
{
    ...
    if (i == 255)
    {
        break;
    }
    ++i;
}

Also habe ich mich gefragt, ist es eine saubere Art und Weise, dies zu tun, ohne einen größeren Datentyp zu verwenden?

EDIT:

  • Ich mag die Version für den Einsatz, weil es macht sein ohne zu denken klare Absicht. Von 0 bis 255 Looping Alle andere Versionen einige Gedanken über erfordern, was los ist und daher eher andere verwirren
  • Ich will nicht, int verwenden, da der Code für eine 8-Bit-Mikrocontroller mit nicht viel Speicher.
War es hilfreich?

Lösung

Was ist mit:

uint8_t i = 0;
do {
    ...
} while (i++ != 255);

Andere Tipps

Ich bin nicht sicher, was du meinst, aber

 uint8_t i = 0;

 do {
    ...
 } while (++i & 255) ;

sollte das tun, was Sie fragen und hat einen ausdrücklichen Hinweis auf 255 (nutzlos, wenn Ihr Compiler C99-Standard ist und uint8_t ist wirklich 8 Bit).

Was mit dem offensichtlichen falsch?

i = 255;
do {
 work();
} while (i--);

Sie scheinen die Nachricht des Zählens von 0 bis 255 durch den Datentyp Sie verwenden, vermitteln zu wollen, aber was ist die Bedeutung von 255? Sie sollten wahrscheinlich diese magische Zahl mit einem Namen #define den Zweck ausdrücklich erklärt. Auch ein Kommentar über die Aussage wäre viel hilfreicher als zu versuchen, „codieren“ all diese Informationen in etwas seltsam schauende Aussagen.

Zum Beispiel:

#define MAX_RETRIES   255
unsigned int retries;

for(retries = 0; retries <= MAX_RETRIES; ++retries)
{
  do_retry_work();
}

Bei Bedarf einen Kommentar ein, warum die Anzahl der Wiederholungen beschränkt sich auf 255 ist.

Ich würde vorschlagen, dass die einfache Lösung:

for (int i = 0; i < 256; ++i) {
   ...
}

wird wahrscheinlich auch gehen, um die effizienteste Lösung.

  1. Auch wenn Sie einen kleineren (1 Byte) Datentyp verwenden. Der C-Compiler fördert es in einen int in jedem Ausdruck.

  2. Auf einem 8-Bit-Controller ein int ist wahrscheinlich 16-Bit. ein Single-Byte-Typ verwendet, wird ein Byte Stapelspeicher nur speichern. Dann wieder kann der Compiler die Variable in einem Register gesetzt, so wird es keine Platzersparnis ohnehin sein.

den Assembler-Code von dem obigen Code erzeugt prüfen, dann entscheiden, ob es braucht (Raum) Optimierung.

in zwei Hälften Count?

uint8_t k = 0;
while (k & 0x80 == 0) {
  work();
  k++;
}
while (k & 0x80 == 1) {
  work();
  k++;
}

Sie so viel Mühe aufwenden ein Byte zu speichern? Ihr letztes Beispiel funktionieren würde, oder man könnte eine Art Kombination aus den ersten und den dritten tun:

for (uint8_t i = 0;;++i)
{
   work();
   if (i == 255)
       break;
}

Still, fragen Sie sich, wenn die zugegebene Hässlichkeit im Code wert, dass ein Byte zu speichern. Wenn Sie mit einer Lösung wie das gehen zusammen tun, dann sollten Sie dokumentieren, warum Sie es nicht die offensichtliche Art und Weise tun.

Nun, wenn Sie weniger als klaren Code klar machen wollen, können Sie immer einen Kommentar hinzufügen;)

Eine Lösung ist es, den Körper der Schleife in einer Funktion zu setzen (oder Makro, wenn die öffentliche Auspeitschung kein Problem ist), und dann:

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

oder wenn Sie lieber erweitern den Umfang von i und C ++ Bereichsregeln gelten:

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

for (uint8_t i(0); (int)i <= 255; ++i)

Es scheint mir vollkommen klar.

Auch wenn Sie einen 1-Byte-Zähler zu verwenden versuchen, Ihr Compiler sehr gut drehen kann es in diese statt:

for (int ii(0); ii <= 255; ++ii) {
    uint8_t i(ii);
    ...
}

Zum Beispiel GCC tut, weil es schneller ist.

$ cat >test.c
void foo(char);
void bar(void) {
    char i;
    for (i = 0; i <= 255; i++)
        foo(i);
}
^D
$ cc -m32 -c -O3 test.c
$ objdump -d test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <bar>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   53                      push   %ebx
   4:   31 db                   xor    %ebx,%ebx
   6:   83 ec 04                sub    $0x4,%esp
   9:   8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
  10:   89 1c 24                mov    %ebx,(%esp)
  13:   83 c3 01                add    $0x1,%ebx
  16:   e8 fc ff ff ff          call   17 <bar+0x17>
  1b:   eb f3                   jmp    10 <bar+0x10>
$ cc -m64 -c -O3 test.c
$ objdump -d test.o

test.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <bar>:
   0:   53                      push   %rbx
   1:   31 db                   xor    %ebx,%ebx
   3:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
   8:   89 df                   mov    %ebx,%edi
   a:   83 c3 01                add    $0x1,%ebx
   d:   e8 00 00 00 00          callq  12 <bar+0x12>
  12:   eb f4                   jmp    8 <bar+0x8>

Nein, es gibt keinen klaren Weg, um es in einfachem alten C zu tun, da die bedingten nach der Erhöhung überprüft wird, und wenn Sie <= 255 vergleichen, werden Sie Schleife für immer, als einen 8-Bit-Wert können nicht 255 überschreiten und beenden.

So wird es.

uint8_t i = 0;
while (1)
{
  /* your stuff */
  if (255 == i++)
    break;
}

Wenn Sie nicht denken, dass gegen 0 Kontrolle (die Umwickeltyps zu sehen) in Ihrem Buch ist klar. Es ist nicht klar, in dir.

Beachten Sie, dass 8-Bit-Typen auf viele Compiler sehr ineffizient sind, unnötige Zeichen produzieren manchmal erstreckt. Sie könnten die uint_least8_t Typ stattdessen verwenden möchten, wird es wahrscheinlich auf die Wortgröße des Systems erweitern und schneller laufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top