Mengapa "++ i ++" tidak valid sementara (++ i) ++ valid?

14

Mari kita pertimbangkan kode berikut:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

Ini mengkompilasi dengan yang berikut ini dengan kesalahan:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

Ini kedengarannya adil bagi saya. Peningkatan postfix memiliki prioritas lebih tinggi daripada kenaikan awalan, sehingga kode diuraikan sebagai int b = ++(i++);dan imerupakan nilai. Karena itu kesalahannya.

Sekarang mari kita pertimbangkan varian ini dengan tanda kurung untuk mengesampingkan prioritas default:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

Kode ini mengkompilasi dan mengembalikan 3. Sendiri, ini terdengar adil bagi saya tetapi tampaknya bertentangan dengan kode pertama.

Pertanyaannya: mengapa (++i)adalah lvalueketika itidak?

Terima kasih!

UPDATE: pesan kesalahan yang ditunjukkan di atas adalah dari gcc (x86-64 9.2). Berikut ini render yang tepat: kesalahan dengan gcc

Dentang x86-64 9.0.0 memiliki pesan yang sangat berbeda: kesalahan dengan dentang

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

Dengan GCC, Anda mendapat kesan bahwa masalahnya ada pada operator postfix dan Anda kemudian dapat mengembara mengapa ++itidak apa-apa sementara itidak, maka pertanyaan saya. Dengan Dentang lebih jelas bahwa masalahnya ada pada operator awalan.

Bktero
sumber
Ini awalnya ditandai dengan C, pasti tidak valid C.
Antti Haapala
Sungguh maaf! Saya berasumsi perilaku itu sama di C ...
Bktero

Jawaban:

23

idan ++ikeduanya adalah nilai, tetapi i++merupakan nilai.

++(i++)tidak dapat valid, karena awalan ++sedang diterapkan i++, yang merupakan nilai. Tetapi (++i)++baik-baik saja karena ++imerupakan nilai.

Perhatikan bahwa dalam C, situasinya berbeda; i++dan ++ikeduanya adalah nilai. (Ini adalah contoh mengapa orang harus berhenti dengan asumsi bahwa C dan C ++ memiliki aturan yang sama. Orang memasukkan asumsi ini ke dalam pertanyaan mereka, yang kemudian harus disangkal.)

Brian
sumber
4

Deklarasi ini

int b = ++i++;

setara dengan

int b = ++( i++ );

Operator increment postfix mengembalikan nilai operan sebelum increment.

Dari Standar C ++ 17 (8.2.6 Peningkatan dan penurunan)

1 Nilai ekspresi postfix ++ adalah nilai operandnya ... Hasilnya adalah nilai awal .

Sementara operator kenaikan unary mengembalikan nilai setelah kenaikannya. Jadi deklarasi ini

int b = (++i)++;

adalah benar. Anda bisa misalnya menulis

int b = (++++++++i)++;

Dari Standar C ++ 17 (8.3.2 Peningkatan dan penurunan)

1 Operand awalan ++ dimodifikasi dengan menambahkan 1. Operand harus merupakan nilai yang dapat dimodifikasi. Jenis operan harus merupakan tipe aritmatika selain cv bool, atau penunjuk ke tipe objek yang terdefinisi sepenuhnya. Hasilnya adalah operan yang diperbarui; itu adalah nilai , dan ini adalah bit-field jika operan adalah bit-field ....

Perhatikan bahwa dalam C kedua operator mengembalikan nilai alih-alih nilai. Jadi dalam C deklarasi ini

int b = (++i)++;

tidak valid.

Vlad dari Moskow
sumber
3

jadi kode diuraikan sebagai int b = ++ (i ++); dan saya adalah nilai.

Tidak. iItu bukan nilai. iadalah nilai. i++adalah nilai (prvalue untuk lebih spesifik).

eerorika
sumber