uint16_tを使用せずにループのためにこれを書くことは可能ですか? が0xFFに達すると、オーバーフローが発生します。C++この8ビットのループを終了する最善の方法
for (uint8_t i = 0; i <= 0xFF; i++)
{
// do something
if (i == 0xFF)
break;
}
uint16_tを使用せずにループのためにこれを書くことは可能ですか? が0xFFに達すると、オーバーフローが発生します。C++この8ビットのループを終了する最善の方法
for (uint8_t i = 0; i <= 0xFF; i++)
{
// do something
if (i == 0xFF)
break;
}
フルレンジをカバーするために、ここでの素敵なフィット感である一方で、私達はちょうど...そう使用して、ループの本体の後にテストを実行する必要があります。オーバーフローとして
uint8_t i = 0;
do {
...
} while (i++ < 0xFF);
符号なしの数字が明確に定義されているため、このループはそれを行うことができます。
uint8_t i = 0;
do {
// use i here
i++;
} while (i);
私オーバーフローが256番目の繰り返しで(0となり)、条件が偽であるため、しばらくは停止します。
注:このトリックは、< 32ビットプラットフォームの場合にのみ役立ちます。 32ビットプラットフォームでは、このトリックが> = 32ビット幅のカウンタを使用するループに変換される可能性が高くなります。
一方、8ビットプラットフォームでは、これは最も効率的で、最小の256反復ループだと思います。
いつもどのように、なぜこれがうまく動作しているのかについて、非常にコメントしてください! [最小驚きの原則](https://en.wikipedia.org/wiki/Principle_of_least_astonishment) –
@MooingDuck:うまくいけば、今はっきりしている。 – geza
奇妙に見えるということは、代替案よりも優れていなければならないことを意味します。それでも、g ++がループ内のコードとコードをどのように比較したかは、両方のソリューションとも100%同一であることがわかりました。 https://godbolt.org/g/ec8RFf体内ループ管理コードを取り除くために、あなたの状態で++ iをすることができます。 –
最短ではありませんが、これを行う最もクールな方法は、すべての可能な値が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は、コンパイル時に配列を生成します。このコードは任意の整数型に使用できます。
それほど大きすぎないのですか? –
はい。 'if'全体を削除します。それは冗長です。 –
'i = 0; do {....} while(++ i); ' –
ifを削除すると、これが無限ループに変わります。 –