++ iとi ++の違いは何ですか?
-
09-06-2019 - |
質問
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
ループの場合、どちらも機能します。 ++ i
はより一般的です。おそらく K& Rで使用されているためです。
いずれの場合でも、ガイドライン「 i ++
よりも ++ i
を優先」"に従ってください。間違いはありません。
++ i
および i ++
の効率性に関するコメントがいくつかあります。学生プロジェクト以外のコンパイラでは、パフォーマンスの違いはありません。これは、生成されたコードを見ると確認できます。コードは同一です。
効率性の質問は興味深いです...ここに私の答えの試みがあります: Cでi ++と++ iのパフォーマンスに違いはありますか?
フロイントのメモでは、 operator ++()
は関数であり、コンパイラーは作成を最適化することを知ることができないため、C ++オブジェクトでは異なります。中間値を保持する一時オブジェクト。
他のヒント
i ++ は Post Increment として知られていますが、 ++ i は Pre 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
の値は、 i
の i
の増分後に j
に割り当てられます。
同様に、 ++ 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
になります。
「効率」について心配しないでください。 (実際、速度)のいずれかが速いです。最近、これらのことを処理するコンパイラがあります。あなたの意図をより明確に示すものに基づいて、使用する意味のあるものを使用してください。
++ i
は値をインクリメントしてから返します。
i ++
は値を返し、次にインクリメントします。
わずかな違いです。
forループの場合は、 ++ i
を使用します。わずかに高速です。 i ++
は、ただ捨てられる余分なコピーを作成します。
i ++
:このシナリオでは、最初に値が割り当てられ、次に増分が行われます。
++ i
:このシナリオでは、最初に増分が行われ、次に値が割り当てられます
以下は画像の視覚化であり、こちらが実例となる素晴らしいビデオです。同じ。
++ i
が i ++
よりわずかに速い理由は、 i ++
がローカルコピーを必要とする可能性があるためです。 ++ i
は決して増加しませんが、iの値は増加します。場合によっては、一部のコンパイラは可能な限りそれを最適化します...しかし、常に可能であるとは限らず、すべてのコンパイラがこれを行うわけではありません。
コンパイラの最適化に頼りすぎないようにしていますので、Ryan Foxのアドバイスに従います。両方を使用できる場合は、 ++ i
を使用します。
どちらを使用しても効果的な結果は同じです。つまり、ループは両方のインスタンスでまったく同じことを行います。
効率の面では、++ iよりもi ++を選択するとペナルティが生じる可能性があります。言語仕様に関しては、ポストインクリメント演算子を使用すると、演算子が動作している値の余分なコピーを作成する必要があります。これは余分な操作の原因になる可能性があります。
ただし、前述のロジックに関する2つの主な問題を考慮する必要があります。
-
最新のコンパイラは素晴らしいです。すべての優れたコンパイラーは、forループで整数の増分を見ていることを認識できるほど賢く、両方のメソッドを同じ効率的なコードに最適化します。プレインクリメントではなくポストインクリメントを使用すると、実際にプログラムの実行時間が遅くなる場合、 terrible コンパイラを使用しています。
-
運用の時間の複雑さの点では、2つの方法は(実際にコピーが実行されている場合でも)同等です。ループ内で実行される命令の数は、増分操作の操作数を大幅に上回るはずです。したがって、大きなサイズのループでは、増分メソッドのペナルティは、ループ本体の実行によって大幅に隠されます。言い換えれば、増分ではなく、ループ内のコードの最適化を心配する方がはるかに適切です。
私の意見では、全体の問題はスタイルの好みに単純に要約されています。プリインクリメントが読みやすいと思う場合は、それを使用してください。個人的には、ポストインクリメントを好みますが、それはおそらく最適化について何も知らないうちに教えられたことだったからでしょう。
これは時期尚早な最適化の典型的な例であり、このような問題は設計上の深刻な問題から私たちの注意をそらす可能性があります。ただし、「ベストプラクティス」では使用法やコンセンサスに統一性がないため、質問するのは良い質問です。
これらは両方とも数値を増やします。 ++ 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
++ i
(プレフィックス操作):増分してから値を割り当てます
(例): int i = 5
、 int b = ++ i
この場合、6が最初にbに割り当てられ、次に7に増分されます。
i ++
(Postfix操作):値を割り当ててからインクリメントします
(例): int i = 5
、 int b = i ++
この場合、最初に5がbに割り当てられ、次に6に増分され、以下同様に続きます。
forループの場合:通常、forループでインクリメントする前に i
の開始値を使用するため、 i ++
が主に使用されます。ただし、プログラムのロジックによって異なる場合があります。
++ 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
今、セマンティクスの違いを理解していると思います(正直なところ、なぜだろうか 人々は読むのではなく、スタックオーバーフローで「演算子Xの意味」を尋ねます。 ご存知のように、本やWebチュートリアルなどです。
とにかく、どちらを使用するかについては、パフォーマンスに関する質問を無視してください。 C ++でも重要ではありません。これは、決定するときに使用すべき原則です 使用するもの:
コードの意味を言ってください。
ステートメントでインクリメント前の値が必要ない場合は、その形式の演算子を使用しないでください。些細な問題ですが、禁止しているスタイルガイドを使用している場合を除きます。 他のすべてを支持するバージョン(別名骨のあるスタイルガイド)を使用する必要があります あなたがやろうとしていることを最も正確に表現するフォーム。
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( Before Increment )
- if
のように増加しますi = 1
に投稿すると、ループは1,2,3,4、n
- pre if
のように増加しますi = 1
ループは2,3,4,5、n
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ループでは、その使用法に違いは見られません。
次のCコードフラグメントは、前後のインクリメント演算子とデクリメント演算子の違いを示しています。
int i;
int j;
インクリメント演算子:
i = 1;
j = ++i; // i is now 2, j is also 2
j = i++; // i is now 3, j is 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 ++でのポインター変数のポスト/プリインクリメント
#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
唯一の違いは、変数の増分と演算子が返す値の演算順序です。
このコードとその出力は違いを説明しています:
#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
に対する演算子 ++
の位置を ++
操作の順序に関連付けます割り当てを尊重
言い換えると:
-
++
beforei
は、割り当てを前行う必要があることを意味します。 -
++
afteri
は、割り当てを 後にインクリメントする必要があることを意味します。
その内部変換は、複数のステートメントと考えることができます。
// case 1 :
i++;
/* you can think as,
* i;
* i= i+1;
*/
// case 2
++i;
/* you can think as,
* i = i+i;
* i;
*/
a = i ++は、aが現在のi値を含むことを意味します a = ++ iは、aにインクリメントされたi値が含まれることを意味します
違いを理解するための例です
int i=10;
printf("%d %d",i++,++i);
output: 10 12/11 11
( printf
関数の引数の評価順序に依存します。これはコンパイラーとアーキテクチャーによって異なります)
説明:
i ++
-&gt; i
が出力され、増分されます。 (10を印刷しますが、 i
は11になります)
++ i
-&gt; i
の値が増加し、値が出力されます。 (12を印刷し、 i
の値も12)