โอเปอเรเตอร์ทำงานอย่างไรใน C


10

ฉันมีคำถามคอมไพเลอร์ทำงานบนรหัสต่อไปนี้

#include<stdio.h>

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

d = 11ผมไม่แน่ใจว่าทำไมผลที่ได้คือ


1
ทำไมคุณถึงไม่แน่ใจ คุณคาดหวังอะไรอีกและทำไม
Gerhardh

2
ฉันไม่จำความหมายที่แม่นยำที่เกี่ยวข้อง แต่คุณอาจสังเกตพฤติกรรมที่ไม่ได้กำหนด
chepner

3
ไม่ @chepner มีจุดลำดับหลังจากการประเมินสภาพของบุคคลที่สามก่อนที่จะประเมินทางเลือกที่เลือก นั่นหลีกเลี่ยงเวกเตอร์ UB ที่ฉันคิดว่าคุณคิด
John Bollinger

ใช่ฉันไม่แน่ใจว่าฉันคิดว่าคอมไพเลอร์จะมีทางเลือก
chepner

คำตอบ:


6

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

  • ค่าของc++คือค่าปัจจุบันของc11 แยกต่างหากcจะเพิ่มขึ้นเป็น 12
  • b == 11เป็นเท็จเนื่องจากbเป็น 12
  • เนื่องจาก(b == c++)เป็นเท็จ(c-1)ใช้ นอกจากนี้การเพิ่มขึ้นของc12 จะต้องเสร็จสิ้นในจุดนี้
  • ตั้งแต่c12 c-1คือ 11
  • d ถูกเตรียมใช้งานกับค่านั้น 11

5

ตามมาตรฐาน C (6.5.15 ตัวดำเนินการแบบมีเงื่อนไข)

4 ตัวถูกดำเนินการแรกถูกประเมิน; มีจุดลำดับระหว่างการประเมินกับการประเมินของตัวถูกดำเนินการที่สองหรือสาม (แล้วแต่จำนวนใดจะถูกประเมิน) ตัวถูกดำเนินการตัวที่สองจะถูกประเมินเฉพาะเมื่อตัวแรกเปรียบเทียบไม่เท่ากันกับ 0 ตัวถูกดำเนินการตัวที่สามจะถูกประเมินเฉพาะเมื่อตัวแรกเปรียบเทียบเท่ากับ 0; ผลที่ได้คือมูลค่าของตัวถูกดำเนินการที่สองหรือสาม (แล้วแต่จำนวนใดจะถูกประเมิน) แปลงเป็นประเภทที่อธิบายด้านล่าง 195

ดังนั้นในการเริ่มต้นการแสดงออกของการประกาศนี้

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

ตัวแปรbจะถูกเปรียบเทียบกับค่าของตัวแปรcเนื่องจากตัวดำเนินการภายหลังการเพิ่มจะส่งคืนค่าของตัวถูกดำเนินการก่อนที่จะเพิ่มขึ้น

เนื่องจากค่าไม่เท่ากัน ( bตั้งค่าเป็น 12 ในขณะที่cตั้งค่าเป็น 11) ดังนั้นนิพจน์ย่อย(c-1)จะถูกประเมิน

ตามคำพูดมีจุดลำดับหลังจากการประเมินสภาพของผู้ประกอบการ มันหมายความว่าหลังจากการประเมินผลของสภาพcมีค่าหลังจากที่ใช้ประกอบการโพสต์ที่เพิ่มขึ้นให้กับตัวแปร12 cผลที่ตามมาคือตัวแปร d ถูกเตรียมใช้งานโดยค่า1( 12 - 1)


2
คำตอบที่ถูกต้องเท่านั้น - ?:เฉพาะกรณีนี้จะต้องตอบโดยกล่าวถึงจุดลำดับ เพราะโดยปกติใน C การรวม++กับการดำเนินการอื่น ๆ ในตัวถูกดำเนินการเดียวกันคือพฤติกรรมที่ไม่ได้กำหนด และรหัสนี้ใช้งานได้อย่างคาดเดาได้เนื่องจาก?:มีกฎเกล็ดหิมะพิเศษหลายแบบ
Lundin

4

เพราะว่าเงื่อนไขเป็นเท็จดังนั้นfalseกรณีที่จะเกิดขึ้นc-1แต่เนื่องจากคุณเพิ่มขึ้นcในสภาพโดยc++จึงอยู่ในขณะนี้c 12ผลลัพธ์จึง 12 - 1 ซึ่งคือ 11

แก้ไข: สิ่งที่ OP เข้าใจผิดคือการเพิ่มโพสต์

ดังนั้นสิ่งที่เกิดขึ้นจริงเป็นเช่นนี้:

#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
ฉันคิดว่า OP หมายถึงลำดับของการดำเนินการc++ตามเงื่อนไข เงื่อนไขเป็นเท็จ แต่จากนั้นจะใช้ค่าเดิมของcการคำนวณc - 1ไม่ใช่เวอร์ชันที่เพิ่มขึ้น
chepner

1
ฉันคิดว่า sincce 12 == 11 + 1 เป็นจริง ...
J0S

แต่นั่นไม่เป็นความจริงเลยตั้งแต่ใช้ค่า c ใหม่หรือฉันพลาดจุดของคุณ?
Eraklon

ฉันคิดว่าอาจมีความเข้าใจผิดระหว่างc++และ++c
ChatterOne

@ N00b c++เป็นผู้ประกอบการหลังการขาย ค่าของc++11 c == 12กับผลข้างเคียงของการทำ ++cจะมีค่า 12
chepner

4

แปลเป็น if-statement แบบปกติแล้วโค้ดของคุณจะเป็นดังนี้:

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

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

เงื่อนงำที่นี่คือ c เพิ่มขึ้นหลังจากตรวจสอบเงื่อนไข คุณป้อนelseสถานะ แต่ c มีค่า 12 อยู่แล้ว


1

อ้างถึงผู้ประกอบการ Ternary

วากยสัมพันธ์

เงื่อนไข ? value_if_true: value_if_false

ดังนั้นคุณเขียน

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

ในสถานการณ์นี้ผลลัพธ์จะเป็น 11 เนื่องจากหลังจากตรวจสอบค่า 'c' จะเพิ่มขึ้น (c + 1 = 12) และหลังจากนั้นจะตั้งค่า 'd' เป็น c (12) -1 ซึ่งเท่ากับ 11

ถ้าคุณใช้เช่น:

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

ค่า "c" จะเพิ่มขึ้นก่อนที่จะตรวจสอบคำสั่งดังนั้นจึงเป็นจริงและค่า "d" จะเป็น c (12) +1 ซึ่งเท่ากับ 13

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.