「i ++ == ++ i」の場合、C開発者はどうしてそんなに興味を持ちますか?[閉まっている]


15

単なるランダムな観察ですが、StackOverflow.comでは、「++ i == i ++」であるかどうかに関する質問があるようです。しかし、この質問は常に聞かれます。過去2か月間に約6〜7回質問されたのを見たと思います。

なぜC開発者がそれに興味を持っているのだろうか?C#およびJava開発者にも同じ概念/質問が存在しますが、C#に関連する質問は1つしか見なかったと思います。

多くの例で++ iを使用しているからですか?人気のある本やチュートリアルがあるからでしょうか?それは、C開発者が「効率」/「パフォーマンス」のために可能な限り1行に詰め込んで、++演算子を使用する「奇妙な」コンストラクトに頻繁に遭遇するためです。


23
(C#開発者としての私にとって、i ++と++ iは同じではありません。違いに依存するコードを書く場合、読みやすくなるようにリファクタリングし、コンパイラとJITterが処理することを期待します。しかし、C#開発者としては、とにかく比較的非効率的であるため、1〜2クロックサイクルを節約しようとはしていません)
Michael Stum

1
新進プログラマーとして、私たちは算術、論理で遊ぶのが大好きで、物事の仕組みに興味があります。私たちがこのような質問を好むのは、それが大きな理由だと思います。それはパスブレイク機能ではないかもしれませんが、確かに興味深いです!そもそも私たちがプログラマーになった理由は?!
チャニ

2
あなたは文字通り表現を参照しています++i == i++か、より一般的には++iandの意味の違いについてi++ですか?
キーストンプソン

回答:


30

少なくともその一部はもう少し簡単だと思います。今でも、このような多くの質問は学年の初め頃から始まり、それらは一年を通して徐々に減少しています。

そのため、それらのかなりの数は、教師が少なくともそれについて少なくとも少し話しているクラスの結果であると推測するのは公平だと思いますが、彼のポイントをあまりうまく説明していません彼は本当に彼ら自身を理解していないからです)。特にこれらの質問をするように思われる人々に基づいて、実際のコーディングに基づいている人はほとんどいません。


14
これは永遠の9月の反対ではありませんか?永遠の9月は、AOLが顧客にUsenetアクセスを提供し始めた時期で、通年9月(学校を始めたばかりの新入生がボードを初心者として攻撃した月)のように思われました。
nlawalker

それは興味深い理論ですが、誰かが教材を理解していなかった場合、必ずしも教師のせいではないかもしれません:多分、学生は(1)授業中に十分な注意を払っていない、(2)前にstackoverflowの答えを探すのが面倒でした同じ質問をもう一度します。
ジョルジオ14

12

Cプログラマーは操作の順序を理解する必要があるためです。C#開発者は、ビット演算子(&、|、〜)や接頭辞演算子を必ずしも使用する必要はありません。通常、他のものを心配しているためです。ただし、C#の開発者が気付いていないのは、日常的に使用する演算子が何をするのか、そしてそれらを適切に使用する方法を知っている必要があるということです。私たちのほとんどは、これが問題になる可能性のある場所を避けています。

あなたの頭の上から、このスニペットの出力は何ですか?

    double x = 5.5;
    Console.WriteLine(x++);
    x = 5.5;
    Console.WriteLine(++x);

熟練したC#開発者の多くは、コンソールへの出力が何であるかを知らないでしょう。


3
+1。このような状況では、修正前と修正後のインクリメント/デクリメント演算子の違いを知ることは価値があります。
マウルス

4
私はちょっとポイントを見て、出力も知りません(5.5と6.5だと思いますが、確信はありません)、そして私にとってはx ++にリファクタリングするので問題ではありません; Console.WriteLine(x); すぐに。私は完全に無知ではありませんが、使いやすさのない大きなコードの匂いだと思います。
マイケルスタム

8
質問に対する答えは、操作の順序、またはプレフィックスとポストフィックスの増分の違いとは関係ありません。定義された動作と未定義の動作の問題です。
デビッドソーンリー

2
今日これに遭遇しました。のようなものif (myList[i++] == item)。賢い。IndexOutOfRange例外のソースを探していることがわかりました...実際、非常に「賢い」。
rmac

6
5.5と6.5であると思いますが++、フロートで使用されるのを見たことがありません。人々はそれをしますか?(私が好む+= 1
バート・ヴァン・Heukelom

8

これは明らかだと思います。C#では、ためint ii++ == ++i常にfalse中です++i == i++確実に、常に真である、と興味を持って誰もがちょうど(それを実行することにより、実際または)C#のルールを学習することでこれを簡単に見つけることができます。

一方、CおよびC ++では、コンパイラ、実行環境、プラットフォームなどに依存するため、未定義に近いので、答えるのははるかに難しい質問なので、多くの人が尋ねます。


+1-しかし、答えるのは本当に難しい質問ではありません。「未定義」は1つの単語です。「それは...に依存する」ものはすべて、ほとんどの人が心配しないものです。1つの特定のプラットフォームのみを記述している場合でも、言語全体として通常のイディオムを使用する必要があります。プリインクリメントおよびポストインクリメント演算子のほとんどの使用は、いくつかの一般的なイディオムの一部です。
Steve314

+1:これは実際に質問に答えます(つまり、行間を読んでいない)。
トーマスエディング

7

それはトリックの質問であるため、人気のある質問です。未定義です。

上記のリンクは、Bjarnes Stroustrupのホームページに関するFAQにあります。このページでは、この質問に具体的に対処し、この構成が未定義である理由を説明しています。それが言うことは:

基本的に、CおよびC ++では、式で変数を2回読み取り、それも書き込む場合、結果は未定義です。

評価の順序が未定義であると、パフォーマンスの良いコードが得られると主張されています。


5

最も可能性が高いのは、Cでは、書くi++++i、ポインタ算術を行うかが本当に重要だからです。そこではi、手術の前後に増加させることが重要です。例を挙げますが、最後にCを書いたのは10年前です...

C#で、私は考えるように私を必要とする状況に遭遇したことがないi++か、++i私の知る限りので、whileループ/のためのために、それは本当に問題ではありません。


3
それは、C#の違いを理解することが重要です-あなただけのために/各ループ内でそれらを使用するように見えるという理由だけでそれはあなたがそれらを見つけることができます唯一の場所だという意味ではありません
STW

それは完全に真実です。
Mladen Prajdic

3
これは質問には関係ありません。質問は違いに関するものではありませんi++++i、同じ表現でそれらを組み合わせます。
デヴィッドソーンリー

@David問題は、なぜCプログラマーがそれを好むのかということです。答えは(C#では重要ではなく、C#では重要です)完全に関連があります。」
フロリアンF 14

2

数年前、これらの演算子は危険だと考えられていたので、それについてさらに情報を掘り当てようとしました。その時点でstackoverflowがアップしていた場合、私はそこにそれを尋ねたでしょう。

今では、いくつかのねじれた人々が次のようなループを書くからです

while( [something] )
{
  a[++j] = ++j;
}

今でも、何が起こるのか、何が起こるのかについてはあまりよくわかりませんが、同じ行に複数の++ [var]が問題を引き起こしていることは明らかです。


2
増分には、Cの割り当ての一部として未定義の動作があります
-tzenes

7
のような割り当てx = ++j;はCで明確に定義されています。上記はj、介在するシーケンスポイントなしで2回変更されるため、未定義です。
マシューフラシェン

2

2つの理由。

++ iの正しい実装は、iをインクリメントしてから返すことです。i ++の正しい実装は、現在の値を保存し、iをインクリメントし、保存した値を返すことです。これらは同義語として重要なので実装されていません。

問題は、等式などの式を評価するときにコンパイラがいつそれらを適用するかです。

同等性テストが最初に行われ、次にプリインクリメント演算子とポストインクリメント演算子が行われる場合、左辺(lhs)と右辺(rhs)が最初に評価される場合とは異なるロジックを記述する必要があります。平等。

それはすべて操作の順序に関するものであり、それが順番に1つのコードに影響を与えます。そして、驚くことではないが、すべての言語が一致しているわけではない。

基本的なテストのリストにより、開発者は、想定が正しいかどうか、実際の実装が言語仕様と一致するかどうかをテストできます。

これは、ポインター、ループ、または値を返す際にあらゆる種類の影響を与える可能性があります。


5
未定義の動作であるため、これに関する基本的なテストは誤解を招く可能性があります。今回の予想どおりに動作する場合、次回の動作を保証するものではありません。
デヴィッドソーンリー

間違った質問に答えました。Cプログラマーがそれを好む理由に答えるべきです。
ヒューゴ

動作は:あなたの第二パラはとにかく(前少なくともC ++ 11に)間違っている++iことです値を使用i+1して、おそらく前またはその後、ある時点では、しかし、次のシーケンスポイント、インクリメント前i
MM

@MattMcNabb-そのための仕様を教えてもらえますか、実装で状況が変わったかどうか知りたいです。CがPDPアセンブリにうまくマッピングされていた時代に、++ iはINC命令を挿入しましたが、サフィックスバージョンはインクリメント後の命令を使用するためにレジスタの値をコピーする必要がありました。あなたが説明した変更の必要性を構成したものは何ですか?
ウォルトストーンバーナー

2

カルチャーショックだと思う。

既に指摘したように、ポストインクリメントなどの実行順序は厳密には定義されていないため、CまたはC ++の式の動作は未定義です。未定義の動作はCでは非常に一般的であり、もちろんその多くはC ++にインポートされました。

別の言語でプログラミングを行った人-プログラミング言語は正確であると想定されていること、およびコンピュータは指示されたとおりに実行することになっているという考えに気付いた人に...まあ、それはショックですCが意図的に曖昧であることを発見します。


Cは、C#が定義されたときに存在していたよりもはるかに多くのプラットフォームをサポートするように設計されているためです。一方、C#は... x86および360で動作しますか?多分ARMも?他に何もありません。それが、C#がさらに多くを定義できる理由です。
DeadMG

++また、Cは最初にPDP-11上に構築されていませんでしたか?自動インクリメント命令があった場所 Cは命令セットを有効に活用できるように、「マシンに近い」ことを望んでいました。
マイクダンラベイ

@MikeDunlavey:いいえ、Cの++--演算子は、PDP-11、これらの演算子はCの前身言語B.参照のことで導入された時に存在しなかったに基づいていなかったcm.bell-labs.com/who/dmr/chist.html、および「自動インクリメント」を検索します。
キーストンプソン

1

おそらく、C開発者は一般的に++インクリメントをより頻繁に使用しているだけかもしれません。Cには配列を反復処理するための「foreach」または同様のステートメントがないことを考えてください。ああ、もちろん、前述のように、算術ポインターです!


1
良い点は、foreachが比較的現代的な概念であることを忘れていました。
マイケルスタム

-1

両方の部分の違い:postとpreincrementは、これら2つのコードがすべての言語で機能するように機能しています。これは言語に依存しません!!!

++i

これは事前増分です。このコードiは、使用される行に値を送信する前に、最初に値を増やします。

i++

これは投稿の増分です。このコードは、使用されている行のi値を増やす前に値を返しますi

別の小さな例では:

int main(void)
{
  int i = 0; 
  int result; 
  result = 10 + ++i; 
  printf("%d \n", result); // = 11 

  int j = 0; 
  result = 10 + j++; 
  printf("%d \n", result);// = 10
  return 0;
}

このコードは、コードパッドで結果をコンパイルします。

これは、演算子のオーバーロードの内部実装に関係しています。

++i 値を直接増やします(したがって、少し速くなります)

i++ 最初に必要な場所に返されたコピーを作成し、その後元の値を i変数の 1ずつ増加します。

これが今明らかになっていることを願っています。


しかし、これは実際の問題を解決するものではありません。なぜC開発者は他の人よりもこれについて質問するのでしょうか。OPは演算子を理解します。
マーティンピーターズ14

また、この答えは事実上間違っています。++i高速でi++はなく、コピーを作成しません。さらに、++iC での動作とC ++ での動作はわずかに異なり、他の言語間では動作しません。
MM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.