697

Cでは、使用の違いは何ですか++iそしてi++そして、これはaの増分ブロックで使用されるべきです。forループ?


20 답변


878

  • ++iの値を増やしますiその後、増分値を返します。

     i = 1;
     j = ++i;
     (i is 2, j is 2)
    
  • i++の値を増やしますiしかし、その元の値を返すiインクリメントされる前に保持されます。

     i = 1;
     j = i++;
     (i is 2, j is 1)
    

のためにforループ、どちらでも動作します。++iおそらくそれが一般的に使用されているからです。K& R

いずれにせよ、ガイドラインに従ってください++iオーバーi++「そして、あなたは失敗することはないでしょう。

の効率性に関するコメントがいくつかあります。++iそしてi++。学生以外のプロジェクトのコンパイラでは、パフォーマンスに違いはありません。これは、生成されたコードを見れば確認できます。これは同じものです。

効率の問題は興味深いです...これが私の答えです。Cのi ++と++ iのパフォーマンスに違いはありますか?

として友達にC ++オブジェクトでは、operator++()は関数で、コンパイラは中間値を保持するために一時オブジェクトの作成を最適化することを知ることができません。


  • この結果、ループが終了条件に到達したときにもう一度実行されるような天気にならないでしょうか。例えば、for(int i=0; i<10; i++){ print i; }これは違います。for(int i=0; i<10; ++i){ print i; }私が理解しているのは、いくつかの言語はあなたが使うものによってあなたに異なる結果を与えるということです。 - jonnyflash
  • iの増分とprintは異なるステートメントになっているので、jonnyflashは、どちらも同じように動作します。これは、Cスタイル++をサポートするすべての言語に当てはまるはずです。 ++ iとi ++の唯一の違いは、同じステートメント内で操作の値を使用するときです。 - Mark Harrison
  • ほとんどの場合、それらは同一のコードを生成するので、私は好みます。i++なぜなら、それは「オペランド演算子」の形式であるからである。代入は、「オペランド演算子値」である。つまり、代入文の場合と同じように、ターゲットオペランドは式の左側にあります。 - David R Tribble
  • @ARUNi++値を増やすことを意味し、値としてeval前のインクリメントする。インクリメントが発生したときではなく、evalの結果そのものが異なります。インクリメント前のeval結果はインクリメントの後で、インクリメント後のeval結果はインクリメントの前ですが、eval結果が作成される前にインクリメントが行われたかに関係なく利用可能実例を見る同じくらい実証しています。 - WhozCraig
  • @sam、一般的なforループでは、++ i部分に副作用(割り当てなど)がないためです。 - Mark Harrison

146

i ++として知られているインクリメント後一方++ iと呼ばれる事前増分

i++

i++インクリメントするのでポストインクリメントi操作が終了した後の1の値。

次の例を見てみましょう。

int i = 1, j;
j = i++;

ここの値j = 1しかしi = 2。ここの値iに割り当てられますjまずiインクリメントされます。

++i

++iインクリメントするのでプリインクリメントi操作前の1の値 その意味はj = i;後に実行されますi++

次の例を見てみましょう。

int i = 1, j;
j = ++i;

ここの値j = 2しかしi = 2。ここの値iに割り当てられますj後にiの増加i。 同様に++i前に実行されますj=i;

あなたの質問のためにforループのインクリメントブロックでどちらを使用する必要がありますか?答えは、あなたはどれでも使えます。それはあなたのforループと同じnoを実行します。何度も。

for(i=0; i<5; i++)
   printf("%d ",i);

そして

for(i=0; i<5; ++i)
   printf("%d ",i);

両方のループは同じ出力を生成します。すなわち0 1 2 3 4

それはあなたがそれを使用している場所にだけ問題になります。

for(i = 0; i<5;)
    printf("%d ",++i);

この場合、出力は次のようになります。1 2 3 4 5


  • 接頭辞と修正後に変数を初期化すると理解しやすくなります。ありがとう。 - Abdul Alim Shakir

32

どちらが速いかという「効率」(実際には速度)については心配しないでください。私達はこれらの事を大事にする最近コンパイラーを持っている。どちらを使用するのが理にかなっているかを問わず、どちらを使用するのかを明確にしてください。


  • これは、'という意味です。実際に(inc | dec)より前の古い値が必要な場合を除き、プレフィックス(inc | dec)を使用します。この値はごく少数の人が使用します。それが何であるかさえ知らない' ..! - underscore_d

27

++i値をインクリメントしてから返します。

i++値を返してから、それを増分します。

微妙な違いです。

forループの場合は、++i少し速いです。i++ただ捨てられる余分なコピーを作成します。


  • 私は少なくともそれが整数のために違いを生むどんなコンパイラも知らない。 - blabla999
  • それは速くはない。値は無視され(副作用のみが有効)、コンパイラはまったく同じコードを生成できます。 - wildplasser

20

i ++: - このシナリオでは、最初に値が割り当てられてから増分が行われます。

++ i: - このシナリオでは、最初に増分が行われ、次に値が割り当てられます

以下は画像のビジュアライゼーションであり、これもまた素晴らしい実用的なビデオです(http://www.youtube.com/watch?v=lrtcfgbUXm4これは同じことを示しています。

enter image description here


19

理由++i できるより少し速いi++ということですi++増分する前に、iの値のローカルコピーを要求することができます。++iしません。場合によっては、コンパイラによっては可能であればそれを最適化してしまうものもありますが、それは必ずしも可能ではなく、すべてのコンパイラがこれを行うわけではありません。

私は、コンパイラの最適化にあまり頼らないようにしているので、Ryan Foxのアドバイスに従います。両方を使用できるときは、++i


  • C ++では、Cの質問に対する答えは-1です。これ以上「ローカルコピー」はありません。の価値のiあなたが文を書くときに値1があるよりも1;。 - R..
  • @R ..理由を説明してくださいまたはリンク元 - Teejay
  • 理由を説明してください - PerelMan
  • @MarwanB:これは本当によくある質問です。10歳近くの回答に対する詳細な回答を別の質問に埋め込むことは、Stack Overflowの使用方法とは異なります。詳細な回答が必要な場合は(おそらくこの回答/コメントを引用して)新しい質問を投稿してください。ただし、すでに回答済みの多くの質問のうちの1つの複製として締め切られる可能性があります。 - R..

11

どちらを使用しても効果は同じです。言い換えれば、ループはどちらの場合も同じことをします。

効率の点では、++ iよりもi ++を選択するとペナルティが生じる可能性があります。言語仕様の観点からは、インクリメント後演算子を使用すると、演算子が作用している値の追加コピーが作成されるはずです。これが余分な操作の原因になる可能性があります。

ただし、前述のロジックに関する2つの主な問題を考慮する必要があります。

  1. 現代のコンパイラは素晴らしいです。すべての優れたコンパイラは、forループ内で整数の増分が発生していることに気付くほど賢く、そして両方のメソッドを同じ効率的なコードに最適化します。プリインクリメントよりもポストインクリメントを使用すると実際にプログラムの実行時間が遅くなる場合は、ひどいコンパイラ。

  2. 操作上の時間の複雑さに関しては、(実際にコピーが実行されている場合でも)2つの方法は同等です。ループの内側で実行されている命令の数は、インクリメント動作における動作の数を著しく支配するはずである。したがって、大きなサイズのループでは、インクリメントメソッドのペナルティは、ループ本体の実行によって大幅に影が薄くなります。言い換えると、インクリメントではなく、ループ内のコードを最適化することを心配する方がはるかに賢明です。

私の意見では、問題全体は単にスタイルの好みにまとめられています。プリインクリメントの方が読みやすいと思われる場合は、それを使用してください。個人的にはポストインクリメントを好みますが、それはおそらく最適化について何か知っている前に教えたことだったからでしょう。

これは時期尚早の最適化の典型的な例であり、このような問題は設計上の深刻な問題から私たちをそらす可能性があります。ただし、「ベストプラクティス」では使用方法や統一感に統一性がないため、質問するのはまだ良い質問です。


8

両方とも数値を増やします。 ++ iは、i = i + 1と同等です。

i ++と++ iはよく似ていますが、まったく同じではありません。どちらも数値をインクリメントしますが、++ iは現在の式が評価される前に数値をインクリメントしますが、i ++は式が評価された後に数値をインクリメントします。

例:

int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3


4

++ iはプリインクリメント、もう一方はポストインクリメント

i ++:要素を取得してから増分します。

++ i:iをインクリメントしてから要素を返す

例:

int i = 0;
printf("i: %d\n", i);
printf("i++: %d\n", i++);
printf("++i: %d\n", ++i);

出力:

i: 0
i++: 0
++i: 2


4

++ i(Prefix operation):値をインクリメントしてから割り当てる

(例):int i = 5、int b = ++ i

この場合、6が最初にbに割り当てられ、次に7まで増分されます。

i ++(Postfix操作):値を割り当ててから増分する

(例):int i = 5、int b = i ++

この場合、5が最初にbに割り当てられ、次に6まで増分されます。

forループの場合:i ++が主に使用されます。通常、for loopをインクリメントする前にiの開始値を使用するからです。ただし、プログラムロジックによっては異なる場合があります。


3

私はあなたが今意味論の違いを理解していると思う(正直なところ私はなぜだろうか 読むのではなく、スタックオーバーフローについて「演算子Xが何を意味するのか」と質問する人がいます、 あなたは知っています、本かウェブチュートリアルか何か。

しかし、とにかく、どちらを使うかということに関しては、パフォーマンスの問題を無視しています。 C ++でも重要性は低いです。これはあなたが決めるときに使うべき原則です どれを使うべきか:

あなたがコードの中で意味していることを言う。

文に増分前の値が必要ない場合は、その形式の演算子を使用しないでください。それは軽微な問題ですが、それを禁止するスタイルガイドを使用して作業しているのでない限り。 他のもの(骨頭のスタイルガイドとも呼ばれる)を完全に優先したバージョンでは、次のようにしてください。 あなたがやろうとしていることを最も正確に表現する形式。

QED、事前増分バージョンを使用します。

for (int i = 0; i != X; ++i) ...


3

違いは以下のこの単純なC ++コードによって理解することができます。

int i, j, k, l;
i = 1; //initialize int i with 1
j = i+1; //add 1 with i and set that as the value of j. i is still 1
k = i++; //k gets the current value of i, after that i is incremented. So here i is 2, but k is 1
l = ++i; // i is incremented first and then returned. So the value of i is 3 and so does l.
cout << i << ' ' << j << ' ' << k << ' '<< l << endl;
return 0;


3

主な違いは

  • i ++ Post(インクリメント後)と
  • ++ i Pre(インクリメント前

    • 投稿するi =1ループは次のように増加します。1,2,3,4,n
    • 前の場合i =1ループは次のように増加します。2,3,4,5,n


2

まもなく: あなたが関数でそれらを書いていないならば、++ iとi ++は同じように働きます。 もしあなたがfunction(i ++)やfunction(++ i)のようなものを使っているなら、違いがわかります。

function(++ i)は最初にiを1だけインクリメントし、その後このiを新しい値を持つ関数に入れます。

function(i ++)は、iを1ずつインクリメントした後で、最初にiを関数に入れます。

int i=4;
printf("%d\n",pow(++i,2));//it prints 25 and i is 5 now
i=4;
printf("%d",pow(i++,2));//it prints 16 i is 5 now


  • 違いは、実際には関数呼び出しとは関係ありません(そして、関数呼び出しをしなくても違いを見つけることができます)。間に違いがありますint j = ++i;そしてint k = i++;関数呼び出しが含まれていない場合でも - Jonathan Leffler

2

事前作成は、同じ行で増分することを意味します。ポストインクリメントとは、行の実行後にインクリメントすることを意味します。

int j=0;
System.out.println(j); //0
System.out.println(j++); //0. post-increment. It means after this line executes j increments.

int k=0;
System.out.println(k); //0
System.out.println(++k); //1. pre increment. It means it increments first and then the line executes

それがOR、AND演算子と来るとき、それはより面白くなります。

int m=0;
if((m == 0 || m++ == 0) && (m++ == 1)) { //false
/* in OR condition if first line is already true then compiler doesn't check the rest. It is technique of compiler optimization */
System.out.println("post-increment "+m);
}

int n=0;
if((n == 0 || n++ == 0) && (++n == 1)) { //true
System.out.println("pre-increment "+n); //1
}

配列内

        System.out.println("In Array");
        int[] a = { 55, 11, 15, 20, 25 } ;
        int ii, jj, kk = 1, mm;
        ii = ++a[1]; // ii = 12. a[1] = a[1] + 1
        System.out.println(a[1]); //12

        jj = a[1]++; //12
        System.out.println(a[1]); //a[1] = 13

        mm = a[1];//13
        System.out.printf ( "\n%d %d %d\n", ii, jj, mm ) ; //12, 12, 13

        for (int val: a) {
            System.out.print(" " +val); //55, 13, 15, 20, 25
        }

C ++ではポインタ変数のpost / pre-increment

#include <iostream>
using namespace std;

int main() {

    int x=10;
    int* p = &x;

    std::cout<<"address = "<<p<<"\n"; //prints address of x
    std::cout<<"address = "<<p<<"\n"; //prints (address of x) + sizeof(int)
    std::cout<<"address = "<<&x<<"\n"; //prints address of x

    std::cout<<"address = "<<++&x<<"\n"; //error. reference can't re-assign because it is fixed (immutable)
}


2

次のCコードは、前後のインクリメント演算子とデクリメント演算子の違いを示しています。

int i; int j;

//インクリメント演算子

i = 1。

j = ++ i。 // iは2、jは2

j = i ++。 // iは現在3、jは2


2

i ++と++ i

この小さなコードは、すでに投稿されている答えとは異なる角度からの違いを視覚化するのに役立ちます。

int i = 10, j = 10;

  printf ("i is %i \n", i);
  printf ("i++ is %i \n", i++);
  printf ("i is %i \n\n", i);

  printf ("j is %i \n", j);
  printf ("++j is %i \n", ++j);
  printf ("j is %i \n", j);

結果は次のとおりです。

//Remember that the values are i = 10, and j = 10

i is 10 
i++ is 10     //Assigns (print out), then increments
i is 11 

j is 10 
++j is 11    //Increments, then assigns (print out)
j is 11 

前後の状況に注意を払う。

forループ

forループのインクリメントブロックでどちらを使用するべきかについては、私たちが決定を下すためにできる最善の方法は良い例を使うことだと思います。

int i, j;

For (i = 0; i <= 3; i++)
    printf (" > iteration #%i", i);

printf ("\n");

for (j = 0; j <= 3; ++j)
    printf (" > iteration #%i", j);

結果は次のとおりです。

> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3 

私はあなたのことは知りませんが、少なくともforループの中で、使い方に違いはありません。


-1

あなたはそれを内部の変換として考えることができます複数の文;

// case 1 :

i++;

/* you can think as,
 * i;
 * i= i+1;
 */

// case 2

++i;

/* you can think as,
 * i = i+i;
 * i;
 */


-3

a = i ++は、aが現在のi値を含むことを意味します a = ++ iはaがインクリメントされたi値を含むことを意味します


  • この答えは正確ではありません。a = i++;に格納されている値を意味しますaの値になりますiインクリメントの前、ただしインクリメントしない'ことを意味しますiインクリメントされていない、これはまったく間違っている - iは増分されますが、式の値は増分前の値です。 - Jonathan Leffler

-5

これが違いを理解するための例です

int i=10;
printf("%d %d",i++,++i);

出力:10 12/11 11(への議論の評価の順序によってprintf関数、コンパイラやアーキテクチャによって異なります)

説明:i++ - >iが表示され、次にインクリメントされます。 (プリント10、i11)になります++i - >ivalueは値を増分して表示します。 (12を印刷し、の値iまた12)


  • 間にシーケンスポイントがないので、これは未定義の動作を引き起こします。i++そして++i - M.M
  • @Lundinは正しいのですが、LHS、RHSのコンマはそれらの間にシーケンスポイントがありますが、2つの式はまだお互いに対してシーケンスされていません - Antti Haapala

リンクされた質問


関連する質問

最近の質問