Bagaimana tepatnya operator?: Bekerja di C?

10

Saya punya pertanyaan, bagaimana kompiler beroperasi pada kode berikut:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

Saya tidak yakin mengapa hasilnya adalah d = 11.

J0S
sumber
1
Kenapa kamu tidak yakin? Apa lagi yang Anda harapkan dan mengapa?
Gerhardh
2
Saya tidak ingat semantik yang tepat terlibat, tetapi Anda mungkin mengamati perilaku yang tidak terdefinisi.
chepner
3
Tidak, @chepner, ada titik urutan setelah mengevaluasi kondisi terner, sebelum mengevaluasi alternatif yang dipilih. Itu menghindari vektor UB saya kira Anda sedang memikirkan.
John Bollinger
Ya, saya tidak yakin di mana saya pikir kompiler akan punya pilihan.
chepner

Jawaban:

6

Dalam int d = (b == c++) ? (c+1) : (c-1);:

  • Nilai c++adalah nilai saat ini c, 11. Secara terpisah, cbertambah menjadi 12.
  • b == 11salah, karena b12.
  • Karena (b == c++)salah, (c-1)digunakan. Selain itu, peningkatan cke 12 harus diselesaikan pada titik ini.
  • Karena c12, c-111.
  • d diinisialisasi ke nilai itu, 11.
Eric Postpischil
sumber
5

Menurut Standar C (operator kondisional 6.5.15)

4 Operan pertama dievaluasi; ada titik urutan antara evaluasinya dan evaluasi operan kedua atau ketiga (mana yang dievaluasi). Operan kedua dievaluasi hanya jika yang pertama membandingkan tidak sama dengan 0; operan ketiga dievaluasi hanya jika yang pertama sebanding dengan 0; hasilnya adalah nilai operan kedua atau ketiga (mana yang dievaluasi), dikonversi ke jenis yang dijelaskan di bawah ini.110)

Jadi dalam ekspresi awal deklarasi ini

int d = (b == c++) ? (c+1) : (c-1);

variabel bdibandingkan dengan nilai variabel ckarena operator post-increment mengembalikan nilai operandnya sebelum menambahkannya.

Karena nilainya tidak sama satu sama lain ( bdiatur ke 12 sementara cdiatur ke 11) maka sub-ekspresi (c-1)dievaluasi.

Menurut kutipan ada titik urutan setelah evaluasi kondisi operator. Ini berarti bahwa setelah evaluasi kondisi cmemiliki nilai 12setelah menerapkan operator pasca kenaikan untuk variabel c. Sebagai hasilnya, variabel d diinisialisasi dengan nilai 1( 12 - 1).

Vlad dari Moskow
sumber
2
Satu-satunya jawaban yang benar - kasus khusus ini harus dijawab dengan menyebutkan titik urutan dalam ?:. Karena biasanya dalam C, menggabungkan ++dengan operasi lain pada operan yang sama adalah perilaku yang tidak terdefinisi. Dan kode ini hanya bisa ditebak karena ?:memiliki berbagai aturan kepingan salju khusus.
Lundin
4

Karena kondisinya salah, maka falsekasusnya akan terjadi:, c-1tetapi karena Anda bertambah cdalam kondisi oleh c++, oleh karena citu sekarang 12. Hasilnya demikian 12 - 1 yaitu 11.

EDIT: Apa yang disalahartikan OP adalah kenaikan pos.

Jadi yang sebenarnya terjadi adalah seperti ini:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}
Eraklon
sumber
1
Saya pikir OP mengacu pada urutan operasi, mengingat c++kondisinya. Kondisi salah, tapi kemudian asli nilai cyang digunakan untuk menghitung c - 1, bukan versi ditambah satu.
chepner
1
Saya pikir ketulusan 12 == 11 +1 itu benar ...
J0S
Tapi itu tidak benar karena nilai c baru digunakan atau apakah saya kehilangan poin Anda?
Eraklon
Saya pikir mungkin ada kesalahpahaman antara c++dan++c
ChatterOne
@ N00b c++adalah operator pasca kenaikan. Nilai c++11, dengan efek samping pembuatan c == 12. ++cakan memiliki nilai 12.
chepner
4

Diterjemahkan ke if-statement reguler, kode Anda akan terlihat seperti ini:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

Petunjuk di sini adalah bahwa c bertambah setelah kondisi diperiksa. Jadi Anda memasuki elsenegara tetapi c sudah memiliki nilai 12 di sana.

Odiseus
sumber
1

Lihat Operator Ternary.

Sintaksis

kondisi ? value_if_true: value_if_false

Jadi, Anda yang menulis

int d = (b == c++) ? (c+1) : (c-1);

Dalam situasi ini, hasilnya akan menjadi 11 karena, setelah jika memeriksa, nilai 'c' meningkat (c + 1 = 12) dan hanya setelah itu ia menetapkan nilai 'd' sebagai c (12) -1 yang merupakan 11.

Jika Anda menggunakan, misalnya:

int d = (b == ++c) ? (c+1) : (c-1);

Nilai "c" akan ditingkatkan sebelum memeriksa pernyataan, jadi itu benar dan nilai "d" akan menjadi c (12) +1 yaitu 13.

Neto Costa
sumber