2017-12-13 6 views
4

uint16_tを使用せずにループのためにこれを書くことは可能ですか? 0xFFに達すると、オーバーフローが発生します。C++この8ビットのループを終了する最善の方法

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

はい。 'if'全体を削除します。それは冗長です。 –

+15

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

+2

ifを削除すると、これが無限ループに変わります。 –

答えて

7

フルレンジをカバーするために、ここでの素敵なフィット感である一方で、私達はちょうど...そう使用して、ループの本体の後にテストを実行する必要があります。オーバーフローとして

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

符号なしの数字が明確に定義されているため、このループはそれを行うことができます。

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

オーバーフローが256番目の繰り返しで(0となり)、条件が偽であるため、しばらくは停止します。

注:このトリックは、< 32ビットプラットフォームの場合にのみ役立ちます。 32ビットプラットフォームでは、このトリックが> = 32ビット幅のカウンタを使用するループに変換される可能性が高くなります。

一方、8ビットプラットフォームでは、これは最も効率的で、最小の256反復ループだと思います。

+2

いつもどのように、なぜこれがうまく動作しているのかについて、非常にコメントしてください! [最小驚きの原則](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) –

+0

@MooingDuck:うまくいけば、今はっきりしている。 – geza

+0

奇妙に見えるということは、代替案よりも優れていなければならないことを意味します。それでも、g ++がループ内のコードとコードをどのように比較したかは、両方のソリューションとも100%同一であることがわかりました。 https://godbolt.org/g/ec8RFf体内ループ管理コードを取り除くために、あなたの状態で++ iをすることができます。 –

1

最短ではありませんが、これを行う最もクールな方法は、すべての可能な値がuint8_tである配列を宣言し、それを反復することです。

#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; 
    } 
} 

struct range structは、コンパイル時に配列を生成します。このコードは任意の整数型に使用できます。

+0

それほど大きすぎないのですか? –

関連する問題