0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[ネタ]for文、i++ も i-- も、同じ条件式で書けるじゃん!

Posted at

i--の呪文を覚えていない

for(int i=0; i < count; i++)

なら自分の名前を入力するくらいの速さでタイピングできるんです。大学時代に呪文として覚えました。でもi--の方は覚えてないんです。

i--の方を書く場合はいっつも悩みます。"<=0" なのか ">=0" なのか。私は不等号が苦手なので、ちょっとだけ時間がかかります。そしてi>=0と書かれていてもあんまりピンときません。

同じ条件式で書ける。(uint)i < (uint)count ならね!

職場では見かけないコードなのではないでしょうか。(私はニートなので、想像で話しています。)

このコードは i>= 0 && i < count と同じ意味になります。indexが配列の範囲内にあるかを判定する際によく使われる、一部界隈では有名なコードです。(もっと有名ですかね?)

これを使えば同じ条件式を使えるね!

for(int i = 0; (uint)i < (uint)count; i++)DoSome();
for(int i = count-1; (uint)i < (uint)count; i--)DoSome();

チャッピーのありがたいお言葉

チャッピーには止められましたが、個人開発では使っていこうと思います。まあ++の方は普通に書くと思いますが。

折り畳み内容の要約 → 使うな

あなた:
for(int i=count-1;(uint)i<(uint)count;i--)という風に書けば、条件判定についてiを足していく場合も下げていく場合も共通した判定にできますか?
ChatGPT:
結論から言うと 「完全に共通化はできるが、
for(int i = count - 1; (uint)i < (uint)count; i--) の書き方は “崩れるケースがあるので危険” です。

以下で詳しく説明します。

✅ この書き方が何を狙っているか
(uint)i < (uint)count は、

i が 0 以上 count−1 以下の間 → true

i が負の値 → unsigned にキャストされ巨大な数になるため false

つまり

i が負になったらループ終了
という性質を利用しています。

⚠️ しかし、この条件は i++ / i-- のどちらにも安全には使えない
▼ i-- の場合(後ろから前へ)
for (int i = count - 1; (uint)i < (uint)count; i--)
典型的な 逆順ループの高速テクニック で、これは基本的に 正しく動く。

止まる条件
i が 0 → 次で -1 → unsigned 変換で巨大に → ループ終了

問題なし。

▼ i++ の場合(前から後ろへ)
for (int i = 0; (uint)i < (uint)count; i++)
これも一応動く。
i<count と同じ効果になる。

⚠️ しかし問題
i が int.MaxValue に達した場合

i++ すると int.MinValue(負)になる
→ unsigned 変換で巨大に
→ ループが即終了して安全に抜ける

これは「まあ安全」とも言えるが、
実は バグの原因になることがある。

❌ 共通化したいという意図には危険がある
✔ 同じ条件式を書きたい
という気持ちは分かるが、この書き方には以下の問題が残ります:

i-- と i++ で終了条件の意味が変わる

i-- →「負になったら終了」

i++ →「count に達したら終了」

→ 見た目は同じだが内部挙動が違い、読みづらい

int オーバーフローを前提にしているため保守性が悪い

他の開発者にはほぼ理解されない書き方
→ コードレビューで必ず止められる

JIT の最適化に与える影響が未定(通常の比較のほうが安定)

👍 安全に共通化する方法
方法 1: 上昇・下降ループを分けるべき
最も安全:

for (int i = 0; i < count; i++) { ... }
for (int i = count - 1; i >= 0; i--) { ... }
方法 2: 条件式の型安全な共通化(上昇/下降を切り替えたいなら)
もし「方向だけ差し替えれば共通化できるコード」にしたいなら

for (int i = start; i != end; i += step)
{
...
}
例えば:

前方向
int start = 0;
int end = count;
int step = 1;
後方向
int start = count - 1;
int end = -1;
int step = -1;
こうすれば安全。

✔ 最終結論
❌ for(int i=count-1;(uint)i<(uint)count;i--) を
i++ / i-- の両方で使うのは安全ではない。

❌ 条件式の共通化としては不適切。
✔ 目的が「ループを高速化したい」なら
普通の i >= 0 / i < count が最適・安全。

必要なら、

JIT の最適化面での比較

MS の List がこの書き方をどう使っているか
なども詳しく説明できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?