2017-12-13 16 views
4

Ist es möglich, dies für Schleife kürzer oder eleganter zu schreiben, ohne uint16_t zu verwenden? Es gibt einen Überlauf, wenn i0xFF erreicht.C++ Was ist der beste Weg, um diese 8-Bit-Schleife zu beenden

for (uint8_t i = 0; i <= 0xFF; i++) 
{ 
    // do something 
    if (i == 0xFF) 
     break; 
} 
+1

Ja. Entferne das ganze 'if'. Es ist überflüssig. –

+15

'i = 0; do {....} while (++ i); ' –

+2

Das Entfernen von if ändert dies in eine Endlosschleife. –

Antwort

7

das gesamte Spektrum abzudecken, müssen wir nur noch nach dem Körper der Schleife den Test zu tun, so dass ein tun mit ... während eine schöne Passform ist hier:

uint8_t i = 0; 
do { 
... 
} while (i++ < 0xFF); 
3

Als Überlauf für Zahlen ohne Vorzeichen gut definiert sind, kann diese Schleife es tun:

uint8_t i = 0; 
do { 
    // use i here 
    i++; 
} while (i); 

i Überlauf (0 wird) an der 256. Iteration und die während stoppt, weil die Bedingung falsch ist.

Hinweis: Dieser Trick lohnt sich nur, wenn Sie auf einer < 32-Bit-Plattform sind. Auf> = 32-Bit-Plattformen besteht eine hohe Wahrscheinlichkeit, dass dieser Trick in eine Schleife umgewandelt wird, die einen 32-Bit breiten Zähler verwendet.

Auf der anderen Seite, auf 8-Bit-Plattformen, denke ich, dass dies die effizienteste und kleinste 256-Iterationsschleife ist.

+2

Bitte kommentieren Sie immer ausführlich, wie und warum das funktioniert! [Prinzip der geringsten Verwunderung] (https://en.wikipedia.org/wiki/Principle_of_least_astonishment) –

+0

@MooingDuck: Hoffentlich ist es jetzt klar. – geza

+0

Während ordentlich und alles, dass es seltsam aussieht, sollte es besser sein als die Alternativen. Um zu sehen, wie g ++ Ihren Code mit dem Code in meiner Schleife verglichen hat, war es interessant zu sehen, dass es für beide Lösungen zu 100% identisch war. https://godbolt.org/g/ec8RFf Sie könnten ++ i in Ihrem Zustand tun, um den In-Body-Loop-Management-Code loszuwerden. –

1

Nicht die kürzeste, aber die coolste Möglichkeit ist, ein Array mit allen möglichen Werten von uint8_t zu deklarieren und darüber zu iterieren.

#include <iostream> 
#include <cstdint> 
#include <limits> 

namespace detail { 
template<typename int_t, int_t cnt, bool not_done, int_t... rest> 
struct range_impl { 
    static constexpr auto& value = range_impl<int_t, cnt - 1, 
     (cnt - 1) != std::numeric_limits<int_t>::min(), cnt, rest...>::value; 
}; 

template<typename int_t, int_t cnt, int_t... rest> 
struct range_impl<int_t, cnt, false, rest...> { 
    static constexpr int_t value[] = { cnt, rest... }; 
}; 

template<typename int_t, int_t cnt, int_t... rest> 
constexpr int_t range_impl<int_t, cnt, false, rest...>::value[]; 
} // detail 

template<typename int_t> 
struct range : public detail::range_impl<int_t, std::numeric_limits<int_t>::max(), true> {}; 

int main(int argc, char** argv) { 
    for(uint8_t i: range<uint8_t>::value) { 
     std::cout << (int) i << std::endl; 
    } 

    for(int8_t i: range<int8_t>::value) { 
     std::cout << (int) i << std::endl; 
    } 
} 

Die Struktur range generiert das Array in Kompilierzeit. Dieser Code kann für jeden Integer-Typ verwendet werden.

+0

Ist das nicht übergroß? –

Verwandte Themen