• ベストアンサー

なぜ、i++なのか?(ものすごくくだらない質問です)

C言語や、それに文法が似ている言語では、 for(i=0; i<10; i++)... のような例をよく見かけます。 ここで、何故か++iよりi++を使うほうを非常によく見かけるのですが、何故なんでしょうか? 単独で使う分にはどちらでも同じなので、実際はどうでもいいのですが。 個人的には、++iは副作用がまずあって、その副作用の結果を返すのに対し、i++は副作用があることは同じですが、「副作用を起こす前の値」を返す演算ということで、i++の方が少々不自然な感じがしますので、++iの方が好きなのですが。 もし、何か特別な理由があることを知ってらっしゃる方がいたらお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.9

C言語の規格書内の例やfor文の説明で、 i++という表現が使用されており、 多くのC言語を教えている書籍や 先人の方々によってそれが伝統的な書き方に なっているからではないでしょうか? 極端な話、変数名だってiである必要もありませんし。。。 また、効率を気にして++iなどにされる方も多いと思いますが、 あくまでも理論上であって、inc命令の使える最近のCPUでは 処理に差が出ないから「よく使われているi++を使う」という人も いると思います。 >++i は処理前、i++ は処理後です。なので処理文中に使うと > 値が違ってきます。 確かにそうですが、for文の(初期化節・条件式・ボイド式)に ついてはループに入る前に評価され、それぞれの節、式に 副作用完了点があるため、前方置換・後方置換どちらで書いても 単項式であるなら、結果は変わりませんしボイド式の中で、 計算順序を気にしなければならない様な複雑な処理を書くべきでは 無いと思います。

noname#130082
質問者

お礼

回答ありがとうございます。 まさか、こんな沢山回答をいただけるとは・・・。 教科書などの書籍の影響ですか。確かにそれも大きいですよね。 昔の教科書とか、確かめてみなければ・・・。 C言語でなくとも、言語の入門書の最初のサンプルが Hellow World になってたり(^^;。 C++言語という名前も、i++の書き方の方が多かったからかもしれませんし。 効率を考えすぎて読みにくいプログラムを作るよりは、CPUや最適化にまかせた方がいいかもしれませんね。 私の質問も、あくまで、前置と後置のどちらでもよい場合に、何故後置が多用されるのか?ということです。 ボイド式以外でも、できるだけ計算順序を勘定に入れなければいけないような記述は避けたほうがいいですよね。私も、インクリメントやデクリメントは式中でなく、出来る限り単独で使う方針です。これは、副作用のある関数を式中に使う場合も同様の注意が必要ですね。

noname#130082
質問者

補足

うわぁ! 何と、K&R「プログラミング言語C」がi++を使ってました。 何とか手に入れたのが古本の「第2版のANSI規格準拠版」なので、はっきりとはわかりませんが、初版でも多分同じなのではないかと思います。 この本によりますと、最初は++iを使ってますが、第2章8節で前置++、--と後置の意味の違いを明記した後は、何故か基本的にi++を使っています。まだ全部を熟読したわけではないのですが、取りあえずこの時点では、何故そうするかの説明は無いようです。 多分、合理的な理由はあるのでしょうが、それとは別に「K&Rでi++を使っているから、たぶんこれが正しいやり方なのだろう」と思って後置の方を使ったプログラマが沢山いたことは間違いないと思います(^^;;;;。 ここらへんが多分正しそうな気がします(^^; K&Rが何故後置を使ったのか?は別質問になりますので、どうしても分からなければ別質問をするとします。取りあえず、考えられることは。 ・K&Rの使っていたコンピュータがi++の方が都合が良かった。 ・while(*s++ = *t++); のようなトリッキーだが便利な機能がCで書けるので、後置を使うことにした(C言語を売り出すためには、Fortran、Cobol、Pascalなどの既存の言語との差別化が必要だった)。 ・後置を使うと for(i ~;i ~;i ~)... という形になって形が綺麗である。 あたりが考えられます。 あと、C++ では 演算子のオーバーロードができるために事情が違うわけです。C++ の場合は後置++の方がほとんどの場合効率が悪いので、後置を使う特別の理由がない限りは前置の方を使うのが正しい、わけです。 ところで、#6さんへの回答への補足に間違いがあったのですが、#6さんが突っ込んでくれないので、自分の間違いの指摘をここでさせていただきます(__)。 Javaではクラスのインスタンスを作るときはnewを使うので勘違いしてしまいました。C++ で後置++を定義するときは、newは使わずに局所変数に自分のコピーを作って、それをreturnするのが正式のやり方なんですね。従って、C++;と単独で使った場合には、returnした後に自動的にインスタンスは破棄されるのでメモリリークは発生しない、わけです。 そのかわり、 A=C++; というようなことをやると、まずCの中のauto変数に自分自身のコピーを作ってそれを返すが、auto変数のインスタンスは消えてしまうので、Aはあらためてクラスのインスタンスを作って生成しなければいけない。つまり、自分自身のコピーを作る、という操作が「2回」必要になるわけです。で、Aのインスタンスもいずれは破棄しなければいけないので、破棄も結局は「2回」やらなければいけないわけですね。確かにこれは効率が悪い(^^;;;;; まあ、私はC++の文法もよく知らないし、C++のプログラムを作ったことは1度もないので、この間違いはご容赦ください(__)。 javaでは、そもそも++の再定義ができないし、newはあってもdeleteはないので「悩む必要がない」わけです。 なるほど。「自由には責任が伴う」ので、javaでは「自由を制限することで、責任も減らす」ためにC++より厳しい規則になっていて、そのかわりC++より悩みを少なくしているわけです(^^; 大分、仕組みが分かってきました(^^)。 結局、質問したことは無駄ではなかったわけです。勉強になりましたから(^^)。 ということで、大体分かったので、何か見落としていることがあって、誰かが突っ込んでくれる可能性があるのでしばらく締め切りは待つことにします。しばらくたっても突っ込みがなければ質問を締め切らせていただきます。

すると、全ての回答が全文表示されます。

その他の回答 (11)

  • kiwa67
  • ベストアンサー率22% (82/357)
回答No.1

今回の例のようなケース(for ループの初期化)では、 ++i より i++ のほうが、見やすいからです。i++ のほうが、変数 i が先に書かれているので、i をインクリメントするとわかりやすいですね。++i だと、++ の後の変数を見ないと、インクリメントする変数がわからないですね。 質問のところにかいてあるように、副作用の有無により、書き分けるケースもあります。

noname#130082
質問者

お礼

お礼が遅くなってすみません。 さっそくの回答、ありがとうございました。 確かに見やすさは大切ですね。 視線は先頭の文字を最初に見るわけですから、この回答は非常に役に立ちました。 何か、いろいろな話題が出てるようなので、締め切る前にいろいろ勉強しないといけなくなってしまいました(^^;;;。

noname#130082
質問者

補足

見易さの意味では、後置の方がfor文では for(i ~ ;i ~ ;i ~ )... となって、整然としている、ということもあるかもしれませんね。

すると、全ての回答が全文表示されます。

関連するQ&A