Cにおいて、使用の違いは何である++i
とi++
、とのインクリメントブロックにおいて使用すべきfor
ループは?
Cにおいて、使用の違いは何である++i
とi++
、とのインクリメントブロックにおいて使用すべきfor
ループは?
回答:
++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
のループ、どちらか動作します。K&Rで++i
使用されているためか、おそらくより一般的です。
いずれにせよ、「好みのガイドラインに従って++i
オーバーi++
」と、あなたは間違って行くことはありません。
効率性に関するコメントがいくつかあります++i
し、i++
。学生以外のプロジェクトのコンパイラでは、パフォーマンスに違いはありません。これは、生成されたコードを確認することで確認できます。
効率の問題は興味深いです...私の回答の試みは次のとおりです: Cのi ++と++ iの間にパフォーマンスの違いはありますか?
以下のよう@OnFreundのため、ノート、それは、C ++オブジェクトの違うoperator++()
関数であり、コンパイラが中間値を保持するために、一時的なオブジェクトの作成を離れて最適化することを知ることができません。
for(int i=0; i<10; i++){ print i; }
これはfor(int i=0; i<10; ++i){ print i; }
私の理解と違いはありませんか。一部の言語では、使用する言語によって異なる結果が得られるということです。
i++
「operand-operator-value」という割り当てである「operand-operator」の形式であるため、私は好みます。つまり、ターゲットオペランドは、代入ステートメントと同じように、式の左側にあります。
i++
し、print i
異なる文であるが、あるためi++;
とi<10
しています。@jonnyflashの発言はそれほど根拠のないものではありません。あなたが持っていると仮定for(int i=0; i++<10){ print i; }
してfor(int i=0; ++i<10){ print i; }
。これらは、@ johnnyflashが最初のコメントで説明した方法とは異なる動作をします。
++ iはPre Incrementと呼ばれるのに対し、i ++はPost Incrementとして知られています。
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(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
。
どちらがより速いかという「効率」(実際には速度)について心配しないでください。最近、これらのことを処理するコンパイラーがあります。あなたの意図をより明確に示すものに基づいて、使用するのに意味のある方を使用してください。
operator++(int)
(postfixバージョン)内では、コードは一時的なものを作成し、それを返す必要があります。コンパイラは常にそれを最適化できると確信していますか?
++i
値をインクリメントしてから返します。
i++
値を返し、それを増分します。
微妙な違いです。
forループの場合は++i
、少し高速なので、を使用します。i++
捨てられるだけの余分なコピーを作成します。
i++
:このシナリオでは、最初に値が割り当てられ、次に増分が発生します。
++i
:このシナリオでは、最初に増分が行われ、次に値が割り当てられます
以下は画像の視覚化であり、ここにも同じことを示す素晴らしい実用的なビデオがあります。
その理由は、++i
することができ、わずかに速くよりもi++
それがあるi++
一方で、それがインクリメントされる前にiの値のローカルコピーを必要とすることができます++i
ませんでした。場合によっては、一部のコンパイラーは、可能であればそれを最適化します...しかし、常に可能であるとは限りません。すべてのコンパイラーがこれを行うわけではありません。
コンパイラーの最適化にあまり依存しないように心がけているので、Ryan Foxのアドバイスに従います++i
。両方を使用できる場合は、を使用します。
i
ステートメントを記述したとき、値の「ローカルコピー」は値1の値よりも多くありません1;
。
どちらかをループで使用した場合の効果的な結果は同じです。つまり、ループは両方のインスタンスでまったく同じことを行います。
効率の点では、++ iよりもi ++を選択するとペナルティが生じる可能性があります。言語仕様に関して、ポストインクリメント演算子を使用すると、演算子が作用する値の追加のコピーが作成されます。これは追加の操作のソースになる可能性があります。
ただし、前述のロジックでは2つの主要な問題を考慮する必要があります。
最新のコンパイラは素晴らしいです。すべての優れたコンパイラーは、forループで整数のインクリメントが見られることを認識するのに十分スマートであり、両方のメソッドを同じ効率的なコードに最適化します。プリインクリメントよりポストインクリメントを使用すると、プログラムの実行時間が長くなる場合は、ひどいコンパイラを使用しています。
運用時間の複雑さに関しては、2つの方法(コピーが実際に実行されている場合でも)は同等です。ループ内で実行される命令の数は、インクリメント操作の操作数を大幅に支配するはずです。したがって、重要なサイズのループでは、ループ本体の実行によって、インクリメントメソッドのペナルティが大幅に覆い隠されます。言い換えると、ループ内のコードをインクリメントよりも最適化することを心配する方がはるかによいでしょう。
私の意見では、問題全体は単純にスタイルの好みに要約されます。プリインクリメントの方が読みやすいと思われる場合は、それを使用してください。個人的には私はポストインクリメントを好みますが、それはおそらく、それが最適化について何かを知る前に私が教えられたものだったからでしょう。
これは時期尚早の最適化の典型的な例であり、このような問題は設計における深刻な問題から私たちをそらす可能性があります。ただし、「ベストプラクティス」には使用方法の統一やコンセンサスがないため、質問するのは依然として良い質問です。
私はあなたがセマンティクスの違いを理解していると思います(正直に言って、本やWebチュートリアルなどを読むのではなく、スタックオーバーフローについて人々が「演算子Xの意味」の質問をするのはなぜでしょうか?
しかしとにかく、どちらを使用するかについては、C ++でも重要ではないパフォーマンスの問題を無視してください。これは、どちらを使用するかを決定するときに使用する必要がある原則です。
コードであなたが意味することを言ってください。
ステートメントでvalue-before-incrementが必要ない場合は、その形式の演算子を使用しないでください。これは小さな問題ですが、1つのバージョンを完全に他のバージョンよりも優先するスタイルガイド(つまり、骨のあるスタイルガイド)で作業しているのでない限り、実行しようとしていることを最も正確に表すフォームを使用する必要があります。
QED、プレインクリメントバージョンを使用:
for (int i = 0; i != X; ++i) ...
違いは、以下の簡単な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;
主な違いは
- i ++ Post(インクリメント後)および
++ i Pre(インクリメント前)
i =1
ループが次のように増加する場合に投稿する1,2,3,4,n
i =1
ループが次のように増分する場合はpre2,3,4,5,n
この小さなコードは、すでに投稿された回答とは異なる角度からの違いを視覚化するのに役立ちます。
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ループのインクリメントブロックでどちらを使用する必要があるかについては、決定を下すためにできる最善の方法は、良い例を使用することだと思います。
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ループでは、その使用法に違いは見られません。
プリクリメントとは、同じ行でインクリメントすることを意味します。ポストインクリメントとは、ラインが実行された後のインクリメントを意味します。
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 ++では、ポインタ変数のポスト/プレインクリメント
#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)
}
まもなく:
++i
そしてi++
、あなたが機能でそれらを書いていない場合と同じ動作します。のようなものを使用した場合、function(i++)
またはfunction(++i)
違いがわかります。
function(++i)
最初にiを1だけインクリメントした後、これi
を新しい値で関数に入れます。
function(i++)
最初i
にi
1 ずつインクリメントした後に関数に入れると言います。
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++;
ます。
唯一の違いは、変数の増分と演算子が返す値の間の演算の順序です。
このコードとその出力は違いを説明しています:
#include<stdio.h>
int main(int argc, char* argv[])
{
unsigned int i=0, a;
a = i++;
printf("i before: %d; value returned by i++: %d, i after: %d\n", i, a, i);
i=0;
a = ++i;
printf("i before: %d; value returned by ++i: %d, i after: %d\n", i, a, i);
}
出力は次のとおりです。
i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1
したがって、基本的++i
にはインクリメントされた後の値を返し、インクリメントさ++i
れる前の値を返します。最後に、どちらの場合でもi
、の値が増加します。
もう一つの例:
#include<stdio.h>
int main ()
int i=0;
int a = i++*2;
printf("i=0, i++*2=%d\n", a);
i=0;
a = ++i * 2;
printf("i=0, ++i*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
return 0;
}
出力:
i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2
違いは、戻り値が別の変数に割り当てられている場合、または演算の優先順位が適用されている(i++*2
とは異なる++i*2
が同じ値(i++)*2
を(++i)*2
返す)他の演算と連結してインクリメントが実行される場合、多くの場合、それらは交換可能です。古典的な例はforループ構文です:
for(int i=0; i<10; i++)
同じ効果があります
for(int i=0; i<10; ++i)
2つの演算子を混同しないように、私はこのルールを採用しました。
++
変数に関する演算子の位置を、割り当てに関する操作i
の順序に++
関連付けます
言い換えれば:
++
before i
は、インクリメントを割り当て前に実行する必要があることを意味します。++
after i
は、割り当て後にインクリメントを実行する必要があることを意味します。a = i ++は現在のi値を含むことを意味しますa = ++ iは増加したi値を含むことを意味します
a = i++;
に格納されてa
いる値はi
、インクリメント前の値になりますが、「インクリメントなし」i
は、インクリメントされないことを意味します。これは完全に間違っi
ています。インクリメントされますが、式の値はインクリメント前の値です。
違いを理解するための例です
int i=10;
printf("%d %d",i++,++i);
出力:(関数10 12/11 11
への引数の評価の順序によって異なりprintf
ます。これはコンパイラーとアーキテクチャーによって異なります)
説明:
i++
-> i
が出力され、その後増分します。(10 を出力しますが、i
11になります)
++i
-> i
値が増分され、値が出力されます。(12を印刷し、12の値i
も)
i++
しては++i