Nilai s++
adalah nilai asli dari s
, sebelum kenaikan, kenaikan terjadi pada waktu yang tidak ditentukan sebelum titik urutan berikutnya.
Karenanya *s++
dan *(s++)
setara: mereka berdua dereferensi nilai asli s
. Ungkapan lain yang sepadan adalah *(0, s++)
dan, bukan untuk orang yang lemah hati, seperti ini:0[s++]
Perhatikan bahwa fungsi Anda harus menggunakan tipe size_t
untuk i
dan tipe pengembaliannya:
size_t str_len(const char *s) {
size_t i = 0;
while (*s++) {
i++;
}
/* s points after the null terminator */
return i;
}
Berikut adalah versi yang berpotensi lebih efisien dengan kenaikan satu per loop:
size_t str_len(const char *s) {
const char *s0 = s;
while (*s++) {
/* nothing */
}
return s - 1 - s0;
}
Bagi mereka yang bertanya-tanya tentang ekspresi aneh di paragraf kedua:
0, s++
adalah turunan dari operator koma ,
yang mengevaluasi bagian kirinya, kemudian bagian kanannya yang merupakan nilainya. karenanya (0, s++)
setara dengan (s++)
.
0[s++]
sama dengan (s++)[0]
dan *(0 + s++)
atau *(s++ + 0)
yang disederhanakan sebagai *(s++)
. Transposing pointer dan ekspresi indeks dalam []
ekspresi tidak sangat umum atau sangat berguna tetapi sesuai dengan standar C.
, s++
hal-hal buruk yang akan terjadi:)
Dalam contoh itu,
s
menunjuk ke'a'
dalam"a"
. Kemudian bertambah dani
juga bertambah. Sekarangs
menunjuk ke nol terminator, dani
adalah1
. Jadi dalam menjalankan selanjutnya melalui loop,*(s++)
adalah'\0'
(yang0
), sehingga loop berakhir, dan nilai saat inii
(yang1
) dikembalikan.Secara umum, loop dijalankan sekali untuk setiap karakter dalam string, dan kemudian berhenti di terminator nol, jadi begitulah ia menghitung karakter.
sumber
s
dimiliki sebelum bertambah. Apa yang Anda gambarkan adalah perilaku++s
(yang memang akan di-hitung oleh satu, dan memanggil UB jika melewati string kosong).Masuk akal:
Itulah mengapa pointer bertambah dan bukan karakter, misalkan Anda miliki
(*s)++
, dalam hal ini karakter akan bertambah dan bukan pointer. Dereferencing berarti bahwa Anda sekarang bekerja dengan nilai yang dirujuk oleh pointer, bukan pointer itu sendiri.Karena kedua operator memiliki prioritas yang sama tetapi asosiatifitas kanan-ke-kiri, Anda bahkan dapat menggunakan hanya
*s++
tanpa tanda kurung untuk menambah pointer.sumber
Operator kenaikan pos meningkatkan nilai operan sebesar 1 tetapi nilai ekspresi adalah nilai asli operan sebelum operasi kenaikan.
Anggap argumen yang diteruskan
str_len()
adalah"a"
. Dalamstr_len()
, pointers
menunjuk ke karakter pertama dari string"a"
. Dalamwhile
lingkaran:meskipun
s
akan bertambah tetapi nilais
dalam ekspresi akan menjadi penunjuk ke karakter yang ditunjuk sebelum kenaikan, yang merupakan penunjuk ke karakter pertama'a'
. Ketika pointers
direferensikan, itu akan memberikan karakter'a'
. Dalam iterasi berikutnya,s
pointer akan menunjuk ke karakter berikutnya yang merupakan karakter nol\0
. Ketikas
dereferenced, ia akan memberi0
dan loop akan keluar. Perhatikan bahwa,s
sekarang akan menunjuk ke satu elemen melewati karakter nol dari string"a"
.sumber