Setelah meneliti, saya membaca bahwa operator increment mengharuskan operan memiliki objek data yang dapat dimodifikasi: https://en.wikipedia.org/wiki/Increment_and_decrement_operators .
Dari sini saya kira itu memberikan kesalahan kompilasi karena (a+b)
merupakan integer sementara dan tidak dapat dimodifikasi.
Apakah pemahaman ini benar? Ini adalah pertama kalinya saya mencoba meneliti masalah jadi jika ada sesuatu yang seharusnya saya cari, mohon saran.
c = a + b + 1
membuat niat Anda lebih jelas dan juga lebih pendek untuk diketik. Operator increment / decrement melakukan dua hal 1. mereka dan argumen mereka membentuk ekspresi (yang dapat digunakan, misalnya dalam loop for), 2. mereka memodifikasi argumen. Dalam contoh Anda, Anda menggunakan properti 1. tetapi bukan properti 2., karena Anda membuang argumen yang dimodifikasi. Jika Anda tidak membutuhkan properti 2. dan hanya ingin ekspresi, maka Anda dapat menulis ekspresi, misalnya x + 1, bukan x ++.Jawaban:
Itu hanya aturan, itu saja, dan mungkin ada untuk (1) membuatnya lebih mudah untuk menulis compiler C dan (2) tidak ada yang meyakinkan komite standar C untuk melonggarkannya.
Secara informal Anda hanya dapat menulis
++foo
jikafoo
dapat muncul di sisi kiri ekspresi tugas sepertifoo = bar
. Karena Anda tidak bisa menulisa + b = bar
, Anda juga tidak bisa menulis++(a + b)
.Tidak ada alasan nyata mengapa
a + b
tidak bisa menghasilkan sementara yang++
dapat beroperasi, dan akibatnya adalah nilai ekspresi++(a + b)
.sumber
++
terkadang memiliki efek samping dari memodifikasi sesuatu dan terkadang tidak.Standar C11 menyatakan di bagian 6.5.3.1
Dan "nilai l yang dapat dimodifikasi" dijelaskan di bagian 6.3.2.1 sub-bagian 1
Jadi
(a+b)
bukan nilai l yang dapat dimodifikasi dan oleh karena itu tidak memenuhi syarat untuk operator kenaikan prefiks.sumber
Anda benar. yang
++
mencoba untuk menetapkan nilai baru untuk variabel asli. Jadi++a
akan mengambil nilaia
, menambahkannya1
dan kemudian menetapkannya kembalia
. Karena, seperti yang Anda katakan, (a + b) adalah nilai temp, dan bukan variabel dengan alamat memori yang ditetapkan, penetapan tidak dapat dilakukan.sumber
Saya pikir Anda sebagian besar menjawab pertanyaan Anda sendiri. Saya mungkin membuat perubahan kecil pada frase Anda dan mengganti "variabel sementara" dengan "rvalue" seperti yang disebutkan C.Gibbons.
Variabel istilah, argumen, variabel sementara, dan sebagainya akan menjadi lebih jelas saat Anda mempelajari model memori C (ini terlihat seperti gambaran umum yang bagus: https://www.geeksforgeeks.org/memory-layout-of-c-program/ ).
Istilah "rvalue" mungkin tampak buram ketika Anda baru memulai, jadi saya harap hal berikut membantu mengembangkan intuisi tentangnya.
Lvalue / rvalue berbicara tentang sisi yang berbeda dari tanda sama dengan (operator penugasan): lvalue = sisi kiri (huruf kecil L, bukan "satu") rvalue = sisi kanan
Mempelajari sedikit tentang bagaimana C menggunakan memori (dan register) akan membantu untuk melihat mengapa perbedaan itu penting. Dalam sapuan kuas yang luas , kompilator membuat daftar instruksi bahasa mesin yang menghitung hasil ekspresi (nilai r) dan kemudian meletakkan hasilnya di suatu tempat (nilai l). Bayangkan seorang kompiler berurusan dengan fragmen kode berikut:
Dalam perakitan pseudocode mungkin terlihat seperti contoh mainan ini:
Operator ++ (dan - mitranya) membutuhkan "tempat" untuk memodifikasi, pada dasarnya apa pun yang dapat bekerja sebagai nilai l.
Memahami model memori C akan membantu karena Anda akan mendapatkan ide yang lebih baik di kepala Anda tentang bagaimana argumen diteruskan ke fungsi dan (akhirnya) bagaimana bekerja dengan alokasi memori dinamis, seperti fungsi malloc (). Untuk alasan serupa Anda mungkin mempelajari beberapa pemrograman perakitan sederhana di beberapa titik untuk mendapatkan ide yang lebih baik tentang apa yang dilakukan kompilator. Juga jika Anda menggunakan gcc , opsi -S "Berhenti setelah tahap kompilasi tepat; jangan merakit." bisa menarik (meskipun saya akan merekomendasikan mencobanya pada potongan kode kecil ).
Sekadar tambahan: Instruksi ++ telah ada sejak 1969 (meskipun itu dimulai pada pendahulu C, B):
Setelah referensi wikipedia itu akan membawa Anda ke tulisan menarik oleh Dennis Ritchie ("R" dalam "K&R C") tentang sejarah bahasa C, ditautkan di sini untuk kenyamanan: http://www.bell-labs.com/ usr / dmr / www / chist.html tempat Anda dapat mencari "++".
sumber
Alasannya adalah bahwa standar membutuhkan operan menjadi nilai l. Ekspresi
(a+b)
tersebut bukan nilai l, jadi menerapkan operator kenaikan tidak diperbolehkan.Sekarang, orang mungkin mengatakan "Oke, itu memang alasannya, tetapi sebenarnya tidak ada alasan * nyata * selain itu" , tetapi sayangnya kata-kata tertentu tentang cara kerja operator secara faktual memang mengharuskan demikian.
Jelas, Anda tidak dapat menulis
E += 1
jikaE
bukan nilai l. Yang memalukan karena orang bisa saja mengatakan: "menambah E per satu" dan selesai. Dalam hal ini, menerapkan operator pada nilai non-l akan (pada prinsipnya) sangat mungkin, dengan mengorbankan membuat kompilator sedikit lebih kompleks.Sekarang, definisi tersebut dapat dengan mudah diubah kata-katanya (saya pikir ini bukan aslinya C tetapi merupakan pusaka dari B), tetapi melakukan hal itu secara mendasar akan mengubah bahasa menjadi sesuatu yang tidak lagi kompatibel dengan versi sebelumnya. Karena keuntungan yang mungkin didapat agak kecil tetapi kemungkinan implikasinya sangat besar, itu tidak pernah terjadi dan mungkin tidak akan pernah terjadi.
Jika Anda mempertimbangkan C ++ selain C (pertanyaan diberi tag C, tetapi ada diskusi tentang kelebihan operator), ceritanya menjadi lebih rumit. Dalam C, sulit untuk membayangkan bahwa ini bisa terjadi, tetapi dalam C ++ hasil dari
(a+b)
bisa jadi sesuatu yang tidak bisa Anda tambahkan sama sekali, atau penambahan bisa memiliki efek samping yang sangat besar (tidak hanya menambahkan 1). Kompilator harus mampu mengatasinya, dan mendiagnosis kasus bermasalah saat terjadi. Pada nilai l, itu masih agak sepele untuk diperiksa. Tidak demikian halnya untuk ekspresi sembarangan apa pun di dalam tanda kurung yang Anda lemparkan pada hal buruk.Ini bukanlah alasan sebenarnya mengapa tidak bisa dilakukan, tetapi ini pasti memberikan penjelasan mengapa orang-orang yang menerapkan ini tidak terlalu senang menambahkan fitur seperti itu yang menjanjikan sedikit manfaat bagi sangat sedikit orang.
sumber
(a + b) mengevaluasi ke nilai r, yang tidak bisa ditambah.
sumber
++ mencoba memberikan nilai ke variabel asli dan karena (a + b) adalah nilai temp, ia tidak dapat melakukan operasi. Dan mereka pada dasarnya adalah aturan dari konvensi pemrograman C untuk membuat pemrograman menjadi mudah. Itu dia.
sumber
Ketika ekspresi ++ (a + b) dilakukan, maka misalnya:
sumber