Operator increment ++ dan decrement -- adalah dua operator paling khas di C. Keduanya merupakan syntactic sugar untuk += 1 dan -= 1, tetapi dengan satu fitur istimewa: bentuk prefix dan postfix menghasilkan nilai yang berbeda. Pada Chapter ini kita akan membedah secara terpisah keduanya: ++i (prefix) yang menaikkan dulu lalu mengembalikan nilai baru, serta i++ (postfix) yang mengembalikan nilai lama baru kemudian menaikkan. Pemahaman perbedaan keduanya krusial karena kesalahan memilih bentuk dapat mengubah hasil ekspresi, terutama saat dipakai dalam assignment atau pointer arithmetic. Kita juga akan menyinggung konsep sequence point yang membatasi pemakaian ++ ganda dalam satu ekspresi—topik yang akan diuraikan tuntas pada Chapter undefined behavior.
Prefix versus Postfix #
Operator ++ dan -- masing-masing memiliki dua bentuk:
- Prefix (
++i,--i): menaikkan/menurunkan variabel terlebih dahulu, lalu mengembalikan nilai baru. - Postfix (
i++,i--): mengembalikan nilai lama sebagai hasil ekspresi, kemudian menaikkan/menurunkan variabel.
Kedua bentuk sama-sama meningkatkan nilai variabel sebesar satu; perbedaannya hanya pada nilai yang dikembalikan oleh ekspresi. Ketika dipakai sebagai statement mandiri tanpa menangkap hasilnya, i++; dan ++i; ekivalen.
#include <stdio.h>
int main(void) {
int i = 5;
printf("Nilai awal i : %d\n", i);
printf("Postfix i++ (cetak i): %d\n", i++); /* cetak 5, lalu i = 6 */
printf("Setelah postfix : %d\n", i);
printf("Prefix ++i (cetak i) : %d\n", ++i); /* i = 7, cetak 7 */
printf("Setelah prefix : %d\n", i);
printf("Postfix i-- (cetak i): %d\n", i--); /* cetak 7, lalu i = 6 */
printf("Setelah postfix : %d\n", i);
printf("Prefix --i (cetak i) : %d\n", --i); /* i = 5, cetak 5 */
printf("Setelah prefix : %d\n", i);
return 0;
}Output yang Dihasilkan:
Nilai awal i : 5
Postfix i++ (cetak i): 5
Setelah postfix : 6
Prefix ++i (cetak i) : 7
Setelah prefix : 7
Postfix i-- (cetak i): 7
Setelah postfix : 6
Prefix --i (cetak i) : 5
Setelah prefix : 5Mari kita telaah baris-baris kode di atas:
- Baris 7 (
printf("Postfix i++ (cetak i): %d\n", i++);): postfixi++mengembalikan nilai lama5yang dicetak, kemudian variabelidinaikkan menjadi6. - Baris 9 (
printf("Prefix ++i (cetak i) : %d\n", ++i);): prefix++imenaikkanidari6menjadi7terlebih dahulu, baru mengembalikan nilai7untuk dicetak. - Baris 11 (
printf("Postfix i-- (cetak i): %d\n", i--);): postfixi--mengembalikan nilai lama7, kemudianiditurunkan menjadi6. - Baris 13 (
printf("Prefix --i (cetak i) : %d\n", --i);): prefix--imenurunkanidari6menjadi5terlebih dahulu, lalu mengembalikan5.
Pemakaian dalam Loop dan Assignment #
Perbedaan prefix dan postfix menjadi penting ketika hasil ekspresinya ditangkap. Dalam loop for, pemakaian i++ atau ++i memberi hasil yang sama karena nilai kembalian tidak dipakai— compiler modern bahkan menghasilkan kode mesin yang identik. Namun dalam assignment seperti y = x++ versus y = ++x, hasilnya berbeda.
#include <stdio.h>
int main(void) {
int counter = 0;
/* Loop while dengan postfix increment */
while (counter < 3) {
printf("Iterasi ke-%d\n", counter);
counter++; /* kenaikan 1, nilai lama dikembalikan */
}
printf("\n");
/* Loop for dengan prefix increment */
for (int i = 0; i < 3; ++i) {
printf("Iterasi for ke-%d\n", i);
}
printf("\n");
/* Akumulasi dengan postfix: hasil berbeda dari +=1 */
int x = 10;
int y = x++; /* y = 10 (nilai lama), x = 11 */
printf("x = %d, y = %d\n", x, y);
int a = 10;
int b = ++a; /* a = 11, b = 11 */
printf("a = %d, b = %d\n", a, b);
return 0;
}Output yang Dihasilkan:
Iterasi ke-0
Iterasi ke-1
Iterasi ke-2
Iterasi for ke-0
Iterasi for ke-1
Iterasi for ke-2
x = 11, y = 10
a = 11, b = 11Pada baris ke-23, y = x++ menyalin nilai lama 10 ke y terlebih dahulu, kemudian x dinaikkan menjadi 11. Sebaliknya pada baris ke-27, b = ++a menaikkan a menjadi 11 terlebih dahulu, baru nilai baru 11 disalin ke b. Kedua hasil akhir variabel x dan a sama (11), tetapi y dan b berbeda.
Increment pada Tipe Lain #
Operator ++ dan -- tidak hanya bekerja pada int. Operator ini juga berlaku pada char, tipe enumerasi, dan pointer. Pada pointer, ++p bukan menambah alamat sebesar satu byte, melainkan menambah alamat sebesar sizeof(*p) byte sehingga pointer otomatis melompat ke elemen array berikutnya. Inilah dasar pointer arithmetic yang akan kita dalami pada Section khusus.
#include <stdio.h>
int main(void) {
char c = 'a';
/* Increment pada tipe non-int */
printf("Karakter awal : %c (%d)\n", c, c);
c++;
printf("Setelah c++ : %c (%d)\n", c, c);
c += 4;
printf("Setelah c+=4 : %c (%d)\n", c, c);
/* Pointer arithmetic: ++ memajukan pointer */
char nama[] = "Budi";
char *p = nama;
printf("\nPointer ke nama[0] : %c\n", *p);
p++;
printf("Setelah p++ : %c\n", *p);
p++;
printf("Setelah p++ lagi : %c\n", *p);
return 0;
}Output yang Dihasilkan:
Karakter awal : a (97)
Setelah c++ : b (98)
Setelah c+=4 : f (102)
Pointer ke nama[0] : B
Setelah p++ : u
Setelah p++ lagi : dPada baris ke-15, c++ menaikkan kode ASCII 'a' (97) menjadi 'b' (98). Pada baris ke-24, p++ membuat pointer p melompat dari alamat nama[0] ke alamat nama[1], sehingga *p sekarang menunjuk karakter 'u'. Pemakaian postfix di sini sengaja untuk konsistensi dengan idiom C klasik, walaupun prefix ++p akan memberi hasil identik dalam konteks ini.
Operator ++ dan -- adalah pintu masuk ke pemrograman idiomatik C. Kombinasinya dengan loop, pointer, dan array menghasilkan kode yang ringkas namun padat makna. Pada Chapter berikutnya kita akan turun ke level bit dengan operator bitwise.