C: Apa perbedaan antara ++ i dan i ++?


888

Dalam C, apa perbedaan antara menggunakan ++idan i++, dan yang harus digunakan dalam blok kenaikan forloop?


10
Tidak yakin poster asli tertarik, tetapi dalam C ++ perbedaan kinerja bisa sangat besar, karena pembuatan objek sementara mungkin mahal untuk jenis yang ditentukan pengguna.
Pada Freund

Jawaban:


1101
  • ++iakan menambah nilai i, dan kemudian mengembalikan nilai yang bertambah.

     i = 1;
     j = ++i;
     (i is 2, j is 2)
  • i++akan menambah nilai i, tetapi mengembalikan nilai asli yang idimiliki sebelum ditambahkan.

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

Untuk satu forloop, keduanya berfungsi. ++itampaknya lebih umum, mungkin karena itulah yang digunakan dalam K&R .

Dalam kasus apapun, ikuti pedoman "lebih memilih ++ilebih i++" dan Anda tidak akan salah.

Ada beberapa komentar mengenai efisiensi ++idan i++. Dalam kompiler non-siswa-proyek, tidak akan ada perbedaan kinerja. Anda dapat memverifikasi ini dengan melihat kode yang dihasilkan, yang akan identik.

Pertanyaan efisiensi menarik ... inilah usaha saya pada jawaban: Apakah ada perbedaan kinerja antara i ++ dan ++ i di C?

Seperti yang dicatat oleh @ OnFreund , ini berbeda untuk objek C ++, karena operator++()merupakan fungsi dan kompiler tidak dapat mengoptimalisasi pembuatan objek sementara untuk menyimpan nilai perantara.


6
Tidak akankah efek ini cuaca loop berjalan sekali lagi setelah mencapai kondisi akhir? Misalnya, for(int i=0; i<10; i++){ print i; } bukankah ini berbeda dari for(int i=0; i<10; ++i){ print i; } pemahaman saya adalah bahwa beberapa bahasa akan memberikan hasil yang berbeda tergantung pada yang Anda gunakan.
aVeRTRAC

27
jonnyflash, keduanya akan beroperasi secara identik, karena peningkatan i dan hasil cetak ada dalam pernyataan yang berbeda. Ini harus menjadi kasus untuk bahasa apa pun yang mendukung C-style ++. Satu-satunya perbedaan antara ++ i dan i ++ adalah ketika menggunakan nilai operasi dalam pernyataan yang sama.
Mark Harrison

16
Karena dalam kebanyakan kasus mereka menghasilkan kode yang identik, saya lebih suka i++karena itu dalam bentuk "operan-operator", ala penugasan "operand-operator-nilai". Dengan kata lain, operan target ada di sisi kiri ekspresi, sama seperti dalam pernyataan penugasan.
David R Tribble

2
@MarkHarrison, itu akan beroperasi secara identik bukan karena i++dan print idalam pernyataan yang berbeda, tetapi karena i++;dan i<10sedang. Komentar @ jonnyflash bukan tidak masuk akal. Misalkan Anda punya for(int i=0; i++<10){ print i; }dan for(int i=0; ++i<10){ print i; }. Ini akan beroperasi secara berbeda dengan cara yang dijelaskan oleh @johnnyflash dalam komentar pertama.
Adam

3
@sam, karena dalam tipikal untuk loop tidak ada efek samping (misalnya, penugasan) di bagian ++ i.
Mark Harrison

175

i ++ dikenal sebagai Post Increment sedangkan ++ i disebut Pre Increment.

i++

i++adalah kenaikan pasca karena kenaikan inilainya sebesar 1 setelah operasi selesai.

Mari kita lihat contoh berikut:

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

Di sini nilai j = 1tetapi i = 2. Di sini nilai iakan ditugaskan jterlebih dahulu kemudian iakan bertambah.

++i

++iadalah pra kenaikan karena inilainya bertambah 1 sebelum operasi. Itu berarti j = i;akan mengeksekusi setelah i++.

Mari kita lihat contoh berikut:

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

Di sini nilai j = 2tetapi i = 2. Di sini nilai iakan ditugaskan jsetelah i kenaikan i. Demikian pula ++iakan dieksekusi sebelumnya j=i;.

Untuk pertanyaan Anda, yang mana yang harus digunakan dalam blok incrementation dari for for? jawabannya adalah, Anda dapat menggunakan salah satunya .. tidak masalah. Ini akan mengeksekusi for for loop no yang sama. kali.

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

Dan

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

Kedua loop akan menghasilkan output yang sama. yaitu 0 1 2 3 4.

Itu hanya masalah di mana Anda menggunakannya.

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

Dalam hal ini output akan menjadi 1 2 3 4 5.


1
Menginisialisasi variabel setelah prefix dan post-fix membantu untuk memahami. Terima kasih.
Abdul Alim Shakir

42

Tolong jangan khawatir tentang "efisiensi" (kecepatan, sungguh) yang mana lebih cepat. Kami memiliki kompiler hari ini yang mengurus hal-hal ini. Gunakan mana pun yang masuk akal untuk digunakan, berdasarkan mana yang lebih jelas menunjukkan niat Anda.


1
yang, saya harap, berarti ' menggunakan awalan (inc | dec) rement kecuali Anda benar-benar membutuhkan nilai lama sebelum (inc | dec), yang sangat sedikit orang lakukan, namun proporsi yang membingungkan dari bahan ajar yang digunakan, membuat kultus kargo pengguna postfix yang bahkan tidak tahu apa itu '..!
underscore_d

Saya tidak yakin bahwa "penyusun hari ini ... mengurus hal-hal ini" secara universal benar. Di dalam custom operator++(int)(versi postfix) kode harus membuat sementara yang akan dikembalikan. Apakah Anda yakin bahwa kompiler selalu dapat mengoptimalkannya?
Peter - Reinstate Monica

36

++i menambah nilainya, lalu mengembalikannya.

i++ mengembalikan nilai, dan kemudian menambahkannya.

Ini perbedaan yang halus.

Untuk for for, gunakan ++i, karena sedikit lebih cepat. i++akan membuat salinan tambahan yang baru saja dibuang.


23
Saya tidak mengetahui adanya kompiler di mana ia membuat perbedaan untuk bilangan bulat setidaknya.
blabla999

4
Itu tidak lebih cepat . Nilai-nilai diabaikan (hanya efek samping yang efektif) dan kompiler dapat / akan menghasilkan kode yang persis sama.
wildplasser

31

i++: Dalam skenario ini pertama-tama nilainya diberikan dan kemudian kenaikan terjadi.

++i: Dalam skenario ini, pertama kenaikan dilakukan dan kemudian nilai diberikan

Di bawah ini adalah visualisasi gambar dan juga di sini adalah video praktis yang bagus yang menunjukkan hal yang sama.

masukkan deskripsi gambar di sini


Bagaimana Anda bisa menaikkan agak tidak ditugaskan?
kouty

@kouty Anda dapat menambah register yang tidak ditugaskan ke variabel.
Polluks

20

Alasannya ++i bisa sedikit lebih cepat daripada i++yang i++dapat memerlukan salinan lokal dari nilai i sebelum bertambah, sementara ++itidak pernah melakukannya. Dalam beberapa kasus, beberapa kompiler akan mengoptimalkannya jika memungkinkan ... tetapi itu tidak selalu memungkinkan, dan tidak semua kompiler melakukan ini.

Saya mencoba untuk tidak terlalu mengandalkan optimisasi kompiler, jadi saya akan mengikuti saran Ryan Fox: ketika saya bisa menggunakan keduanya, saya gunakan ++i.


11
-1 untuk jawaban C ++ untuk pertanyaan C. Tidak ada lagi "salinan lokal" dari nilai iselain dari nilai 1 ketika Anda menulis pernyataan 1;.
R .. GitHub BERHENTI MEMBANTU ICE

14

Hasil efektif menggunakan salah satu dalam satu lingkaran adalah identik. Dengan kata lain, loop akan melakukan hal yang persis sama di kedua instance.

Dalam hal efisiensi, mungkin ada penalti yang terlibat dengan memilih i ++ lebih dari ++ i. Dalam hal spesifikasi bahasa, menggunakan operator pasca kenaikan harus membuat salinan tambahan dari nilai yang digunakan operator. Ini bisa menjadi sumber operasi tambahan.

Namun, Anda harus mempertimbangkan dua masalah utama dengan logika sebelumnya.

  1. Kompiler modern sangat bagus. Semua kompiler yang baik cukup pintar untuk menyadari bahwa ia melihat peningkatan bilangan bulat dalam for-loop, dan itu akan mengoptimalkan kedua metode ke kode efisien yang sama. Jika menggunakan post-increment lebih dari pre-increment sebenarnya menyebabkan program Anda berjalan lebih lambat, maka Anda menggunakan kompilator yang mengerikan .

  2. Dalam hal kompleksitas waktu operasional, kedua metode (bahkan jika salinan benar-benar dilakukan) adalah setara. Jumlah instruksi yang dilakukan di dalam loop harus mendominasi jumlah operasi dalam operasi kenaikan secara signifikan. Oleh karena itu, dalam setiap loop dengan ukuran signifikan, penalti metode kenaikan akan dibayangi secara besar-besaran oleh eksekusi loop body. Dengan kata lain, Anda jauh lebih baik khawatir tentang mengoptimalkan kode dalam loop daripada kenaikan.

Menurut pendapat saya, seluruh masalah hanya bermuara pada preferensi gaya. Jika Anda merasa pra-kenaikan lebih mudah dibaca, maka gunakan. Secara pribadi, saya lebih suka post-incrment, tapi itu mungkin karena itu yang saya pelajari sebelum saya tahu apa-apa tentang optimasi.

Ini adalah contoh klasik dari pengoptimalan prematur, dan masalah seperti ini berpotensi mengalihkan perhatian kita dari masalah serius dalam desain. Namun, ini masih merupakan pertanyaan yang bagus untuk ditanyakan, karena tidak ada keseragaman dalam penggunaan atau konsensus dalam "praktik terbaik".


13

Mereka berdua menambah jumlahnya. ++isetara dengan i = i + 1.

i++dan ++isangat mirip tetapi tidak persis sama. Keduanya menambah angka, tetapi ++imenambah angka sebelum ekspresi saat ini dievaluasi, sedangkan i++menambah angka setelah ekspresi dievaluasi.

Contoh:

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

8

++i(Prefix operasi): Peningkatan- dan kemudian memberikan nilai
(misalnya): int i = 5, int b = ++i Dalam hal ini, 6 ditugaskan untuk b pertama dan kemudian bertahap ke 7 dan seterusnya.

i++(Postfix operasi): Penerima dan kemudian menambahkan nilai
(misalnya): int i = 5, int b = i++ Dalam hal ini, 5 ditugaskan untuk b pertama dan kemudian bertahap ke 6 dan seterusnya.

Incase of for loop: i++sebagian besar digunakan karena, biasanya kami menggunakan nilai awal isebelum menambahkan untuk loop. Tetapi tergantung pada logika program Anda, itu mungkin berbeda.


7

++i: adalah pra-kenaikan yang lain adalah pasca-kenaikan.

i++: dapatkan elemen dan kemudian menambahkannya.
++i: increments i dan kemudian mengembalikan elemen.

Contoh:

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

Keluaran:

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

5

Saya berasumsi Anda memahami perbedaan dalam semantik sekarang (meskipun jujur ​​saya bertanya-tanya mengapa orang bertanya 'apa arti operator X' pada stack overflow daripada membaca, Anda tahu, buku atau tutorial web atau sesuatu.

Tapi bagaimanapun, sejauh mana yang digunakan, abaikan pertanyaan kinerja, yang sepertinya tidak penting bahkan di C ++. Ini adalah prinsip yang harus Anda gunakan ketika memutuskan mana yang akan digunakan:

Katakan apa yang Anda maksud dalam kode.

Jika Anda tidak membutuhkan nilai sebelum kenaikan dalam pernyataan Anda, jangan gunakan bentuk operator itu. Ini masalah kecil, tetapi kecuali jika Anda bekerja dengan panduan gaya yang melarang satu versi untuk mendukung versi yang lain sama sekali (alias panduan gaya berkepala dingin), Anda harus menggunakan formulir yang paling tepat mengungkapkan apa yang Anda coba lakukan.

QED, gunakan versi pra-kenaikan:

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

5

Perbedaannya dapat dipahami oleh kode C ++ sederhana di bawah ini:

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;

5

Perbedaan utama adalah

  • i ++ Post ( Setelah Bertambah ) dan
  • ++ i Pra ( Sebelum Bertambah )

    • memposting jika i =1 loop bertambah suka1,2,3,4,n
    • pre jika i =1 loop bertambah suka2,3,4,5,n

5

i ++ dan ++ i

Kode kecil ini dapat membantu memvisualisasikan perbedaan dari sudut yang berbeda dari jawaban yang sudah diposting:

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);

Hasilnya adalah:

//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 

Perhatikan situasi sebelum dan sesudah.

untuk loop

Adapun yang salah satunya harus digunakan dalam blok incrementation dari for for, saya pikir yang terbaik yang bisa kita lakukan untuk mengambil keputusan adalah menggunakan contoh yang baik:

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);

Hasilnya adalah:

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

Saya tidak tahu tentang Anda, tetapi saya tidak melihat perbedaan dalam penggunaannya, setidaknya dalam perulangan for.


5

Fragmen kode C berikut menggambarkan perbedaan antara operator kenaikan dan penurunan pra dan pasca:

int  i;
int  j;

Operator tambahan:

i = 1;
j = ++i;    // i is now 2, j is also 2
j = i++;    // i is now 3, j is 2

4

Pre-crement berarti kenaikan pada baris yang sama. Penambahan pasca berarti peningkatan setelah garis dieksekusi.

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

Ketika datang dengan OR, DAN operator, itu menjadi lebih menarik.

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
}

Dalam Array

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
}

Dalam C ++ post / pre-increment variabel pointer

#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)
}

4

Segera:

++idan i++berfungsi sama jika Anda tidak menuliskannya dalam suatu fungsi. Jika Anda menggunakan sesuatu seperti function(i++)atau function(++i)Anda dapat melihat perbedaannya.

function(++i)mengatakan kenaikan pertama i dengan 1, setelah itu masukkan ini ike dalam fungsi dengan nilai baru.

function(i++)mengatakan dimasukkan pertama ike dalam fungsi setelah kenaikan isebesar 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

2
Perbedaannya tidak benar-benar terkait dengan panggilan fungsi (dan Anda dapat melihat perbedaannya tanpa membuat panggilan fungsi). Ada perbedaan antara int j = ++i;dan int k = i++;bahkan ketika tidak ada panggilan fungsi yang terlibat.
Jonathan Leffler

3

Satu-satunya perbedaan adalah urutan operasi antara kenaikan variabel dan nilai yang dikembalikan operator.

Kode ini dan hasilnya menjelaskan perbedaannya:

#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);
}

Output adalah:

i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1

Jadi pada dasarnya ++imengembalikan nilai setelah itu bertambah, sementara ++imengembalikan nilai sebelum itu bertambah. Pada akhirnya, dalam kedua kasus tersebuti akan nilainya bertambah.

Contoh lain:

#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;
}

Keluaran:

i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2

Seringkali tidak ada perbedaan

Perbedaannya jelas ketika nilai yang dikembalikan ditugaskan ke variabel lain atau ketika kenaikan dilakukan dalam penggabungan dengan operasi lain di mana operasi diutamakan diterapkan ( i++*2berbeda dari ++i*2, tetapi (i++)*2dan (++i)*2mengembalikan nilai yang sama) dalam banyak kasus mereka dipertukarkan. Contoh klasik adalah sintaks for loop:

for(int i=0; i<10; i++)

memiliki efek yang sama

for(int i=0; i<10; ++i)

Aturan untuk diingat

Untuk tidak membuat kebingungan antara kedua operator saya mengadopsi aturan ini:

Kaitkan posisi operator ++sehubungan dengan variabel ike urutan ++operasi sehubungan dengan penugasan

Diucapkan dengan kata lain:

  • ++ sebelum i berarti penambahan harus dilakukan sebelum penugasan;
  • ++ setelah i sarana tambahan harus dilakukan setelah penugasan:

3

Anda dapat menganggap konversi internal itu sebagai beberapa pernyataan ;

  • kasus 1
i++;

Anda bisa menganggapnya sebagai,

i;
i = i+1;
  • kasus 2
++i;

Anda bisa menganggapnya sebagai,

i = i+i;
i;

-3

a = i ++ berarti a berisi nilai i saat ini a = ++ i berarti a berisi nilai i yang bertambah


10
Jawaban ini tidak akurat. a = i++;berarti nilai yang disimpan dalam aakan menjadi nilai isebelum kenaikan, tetapi 'tanpa penambahan' menyiratkan bahwa itidak bertambah, yang sama sekali salah - ibertambah, tetapi nilai ekspresi adalah nilai sebelum kenaikan.
Jonathan Leffler

-6

Berikut adalah contoh untuk memahami perbedaannya

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

keluaran: 10 12/11 11(tergantung pada urutan evaluasi argumen terhadapprintf fungsi, yang bervariasi antar kompiler dan arsitektur)

Penjelasan: i++-> idicetak, lalu ditambahkan. (Mencetak 10, tetapi iakan menjadi 11) ++i-> ipeningkatan nilai dan mencetak nilai. (Mencetak 12, dan nilai ijuga 12)


11
Hal ini menyebabkan perilaku yang tidak terdefinisi karena tidak ada titik urutan antara i++dan++i
MM

@Lundin apakah itu benar, LHS, RHS koma memiliki titik sekuen di antara mereka tetapi 2 ekspresi masih saling berurutan satu sama lain
Antti Haapala
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.