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.


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.

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).


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);
}

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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.