私は現在いくつかのコードをデバッグしています、そして私はこの行に出くわしました:
for (std::size_t j = M; j <= M; --j)
(休暇中の上司によって書かれました。)
それは私には本当に奇妙に見えます。
それは何をするためのものか?私には、それは無限ループのように見えます。
私は現在いくつかのコードをデバッグしています、そして私はこの行に出くわしました:
for (std::size_t j = M; j <= M; --j)
(休暇中の上司によって書かれました。)
それは私には本当に奇妙に見えます。
それは何をするためのものか?私には、それは無限ループのように見えます。
Mたまたまの最大値になった場合はsize_tどうなりますか?あなたはまだそれが賢いと思いますか?
#define TRUE FALSEそして休日に行きます。
回答:
std::size_tC ++標準によってunsignedタイプであることが保証されています。また、unsignedタイプを0からデクリメントすると、標準では、その結果がそのタイプの最大値になることが保証されます。
そのラップアラウンド値は常にM1以上であるため、ループは終了します。
したがってj <= M、unsigned型に適用する場合は、「ループをゼロまで実行してから停止する」という便利な方法です。
j必要以上に大きく実行したり、スライド演算子 を使用したりするなどの代替手段for (std::size_t j = M + 1; j --> 0; ){があります。これらは、より多くの入力が必要ですが、ほぼ間違いなく明確です。ただし、(最初の検査で発生する当惑する効果を除いて)1つの欠点は、Javaなどの符号なし型のない言語にうまく移植できないことだと思います。
上司が選択したスキームは、unsignedセットから可能な値を「借用」することにも注意してください。この場合、Mセットstd::numeric_limits<std::size_t>::max()が正しい動作をしないことが発生します。実際、その場合、ループは無限大です。(それはあなたが観察していることですか?)あなたはコードにその効果へのコメントを挿入するべきであり、そしておそらくその特定の条件で主張するべきです。
Mないことを条件としstd::numeric_limits<std::size_t>::max()ます。
std::numeric_limits<std::size_t>::max()、その後M + 1はゼロになり、for (std::size_t j = M + 1; j --> 0; )すべてのループになるではないループ。
size_tが64ビットであると仮定すると、エッジケースでの誤った動作を観察するには数百年かかります。(オプティマイザーがループを取り除くことができる場合を除く。)
上司がおそらくやろうとしていたことはM、ゼロまでカウントダウンし、各数値に対して何らかのアクションを実行することでした。
残念ながら、それが実際に無限ループをもたらすエッジケースがあります。それはあなたが持つことができるM最大size_t値です。また、符号なしの値をゼロからデクリメントしたときに何が行われるかは明確に定義されていますが、特に上司の試みの欠点のない完全に実行可能な解決策があるため、コード自体はずさんな考え方の例であると私は主張します。
そのより安全なバリアント(そして私の意見では、より厳しいスコープ制限を維持しながら、より読みやすく)は次のようになります。
{
std::size_t j = M;
do {
doSomethingWith(j);
} while (j-- != 0);
}
例として、次のコードを参照してください。
#include <iostream>
#include <cstdint>
#include <climits>
int main (void) {
uint32_t quant = 0;
unsigned short us = USHRT_MAX;
std::cout << "Starting at " << us;
do {
quant++;
} while (us-- != 0);
std::cout << ", we would loop " << quant << " times.\n";
return 0;
}
これは基本的にと同じことを行い、すべての値をunsigned short処理することがわかります。
Starting at 65535, we would loop 65536 times.
do..while上記のコードのループを上司が基本的に行ったことに置き換えると、無限ループになります。それを試してみてください:
for (unsigned int us2 = us; us2 <= us; --us2) {
quant++;
}
0です。なぜfor(size_t j = M; j-- != 0; )ですか?
numeric_limits<size_t>::max()ます。
M == 0要素0処理し、それがされていないになりますし、エッジケースを持っています。私のポストチェックdo..while方法を使用すると、エッジケースが完全に排除されます。で試してみるとM == 1、1と0の両方が実行されることがわかります。同様に、max_size_t(それが何であれ)で開始すると、その時点で正常に開始され、ゼロまでデクリメントされます。
exitif」、つまりを使用しているため、「構造化コードではない」と言う人の使用を動機付けます{ j =M; for(;;){ f(j); if( j == 0 )break; j -= 1; } }。Cには名前付きループがないため、ネストされbreakたgoto場合は、をaに置き換える必要がある場合もあります。「構造化」が「チャンクについての推論の影響を受けやすい」を意味する場合、それは構造化されており(レイアウトが役立ちます!)、また「事前条件と事後条件についての推論による正式な検証の影響を受けやすい」ことを意味します。この場合はj--機能しますが、より複雑な遷移が必要な場合は、exitifスタイルが正当化される可能性があります。
size_tは符号なしであるため、ゼロを非推奨にしようとしたときに最大値にラップアラウンドしてループを終了することが保証されています。それでも恐ろしいコードです。