เหตุใดบูลีนประเภทใน C ++ จึงสนับสนุน แต่ไม่ใช่ -


29

ทำไมโอเปอเรเตอร์ถึง--ไม่มีอยู่สำหรับบูลในขณะนั้นสำหรับโอเปอเรเตอร์++?

ฉันลองใช้ C ++ แล้วและฉันไม่รู้ว่าคำถามของฉันใช้ได้กับภาษาอื่นหรือไม่ ฉันยินดีที่จะรู้ว่ายัง

ฉันรู้ว่าฉันสามารถใช้โอเปอเรเตอร์++กับบูล มันทำให้บูลใด ๆ เท่ากับจริง

bool b = false;
b++;
// Now b == true.

ทำไมเราไม่สามารถใช้โอเปอเรเตอร์--ในทางตรงกันข้ามได้

bool b = true;
b--;
// Now b == false;

มันไม่มีประโยชน์มาก แต่ฉันอยากรู้


8
คำถามเกี่ยวกับ StackOverflowนี้อาจเป็นความกระจ่าง
Blrfl

ดังนั้นเหตุผลทางประวัติศาสตร์ ขอบคุณสำหรับลิงค์ คุณช่วยเขียนคำตอบและฉันตอบได้ไหม?
aloisdg พูดว่า Reinstate Monica

ลิงค์เพียงอย่างเดียวไม่ได้คำตอบที่ดีและไม่มีกลไกที่ดีในการทำเครื่องหมายคำถามซ้ำกับบางสิ่งในไซต์ SE อื่น
Blrfl

1
ดังนั้นเราควรเปิดหัวข้อใน meta.stackexchange.com หรืออะไรซักอย่าง ฉันคิดว่าคุณควรจะได้รับกรรมสำหรับการเชื่อมโยงที่ดีและถ้าใครบางคน upvote คุณผู้เขียนจากคำตอบเดิมควรได้รับกรรม ที่จริงแล้วคำถามดั้งเดิมก็ควรได้รับกรรมเช่นกัน
aloisdg พูดว่า Reinstate Monica

2
@aloisdg cross site dups เป็นปัญหาเก่าของ MSO ติดตามคำถามที่เชื่อมโยงเพื่อรับมุมมองที่กว้างขึ้น

คำตอบ:


53

ในสมัยก่อนของ C ไม่มีประเภทบูลีน ผู้คนใช้intสำหรับการจัดเก็บข้อมูลบูลีนและใช้งานได้เป็นส่วนใหญ่ ซีโร่นั้นผิดและทุกอย่างก็เป็นจริง

สิ่งนี้หมายความว่าถ้าคุณทำint flag = 0;และหลังจากนั้นflag++ค่านี้จะเป็นจริง สิ่งนี้จะใช้งานได้ไม่ว่าค่าของธงคืออะไร(เว้นแต่ว่าคุณจะทำมันมากมันจะกลิ้งไปมาและคุณกลับมาที่ศูนย์ แต่ให้เพิกเฉยต่อสิ่งนั้น) - เพิ่มค่าสถานะเมื่อค่าของมันคือ 1 จะให้ 2 ซึ่งยังคง จริง

บางคนใช้สิ่งนี้โดยไม่มีเงื่อนไขในการตั้งค่าบูลีนเป็นจริง ฉันไม่แน่ใจว่ามันจะกลายเป็นสำนวนแต่ในบางรหัส

สิ่งนี้ไม่เคยได้ผล--เพราะถ้าค่าเป็นอย่างอื่นที่ไม่ใช่ 1 (ซึ่งอาจเป็นได้) ค่านั้นก็จะไม่ผิด และถ้ามันเป็นเท็จ ( 0) และคุณทำโอเปอเรเตอร์ลดค่าลงมันจะไม่เป็นเท็จ

เมื่อย้ายรหัสจาก C ถึง C ++ ในช่วงแรกมันสำคัญมากที่รหัส C ที่รวมอยู่ใน C ++ ยังคงสามารถใช้งานได้ ดังนั้นในข้อกำหนดสำหรับ C ++ (ส่วน 5.2.6 (หน้า 71)) จะอ่าน:

ค่าที่ได้รับจากการใช้ postfix ++ คือค่าที่ตัวถูกดำเนินการมีก่อนใช้ตัวดำเนินการ [หมายเหตุ: ค่าที่ได้รับคือสำเนาของค่าดั้งเดิม] ตัวถูกดำเนินการจะเป็นค่า lvalue ที่สามารถแก้ไขได้ ประเภทของตัวถูกดำเนินการจะต้องเป็นประเภทเลขคณิตหรือตัวชี้ไปยังประเภทวัตถุที่สมบูรณ์ หลังจากสังเกตผลลัพธ์แล้วค่าของวัตถุนั้นจะถูกปรับเปลี่ยนโดยการเพิ่ม 1 ลงไปยกเว้นว่าวัตถุนั้นเป็นชนิดboolซึ่งในกรณีนั้นจะถูกตั้งค่าเป็นจริง [หมายเหตุ: การใช้งานนี้เลิกใช้แล้วโปรดดูภาคผนวกง]

ตัวถูกดำเนินการของ postfix - เป็น decremented analogously ไปกับ Postfix ++ boolผู้ประกอบการยกเว้นว่าถูกดำเนินการจะต้องไม่เป็นชนิด

สิ่งนี้ถูกกล่าวถึงอีกครั้งในส่วน 5.3.2 (สำหรับตัวดำเนินการส่วนนำหน้า - 5.2.6 ใช้กับ postfix)

อย่างที่คุณเห็นสิ่งนี้เลิกใช้แล้ว (ภาคผนวก D ในเอกสารหน้า 709) และไม่ควรใช้

แต่นั่นเป็นเหตุผล และบางครั้งคุณอาจเห็นรหัส แต่อย่าทำ


5
"บางคนใช้สิ่งนี้โดยไม่มีเงื่อนไขในการตั้งค่าบูลีนเป็นจริง" ลองเรียกพวกเขาว่าคนโง่เขลาไม่ใช่คน
Deduplicator

@Dupuplicator: อาจเป็นเรื่องของประสิทธิภาพ: การโหลดค่าลงในตัวแปรอาจใช้เวลาประมวลผลมากขึ้นกว่าการเพิ่มตัวแปร แน่นอนว่านี่อาจไม่สำคัญกับคอมพิวเตอร์สมัยใหม่
Giorgio

1
@Giorgio ที่มีโอกาสมาก โปรดจำไว้ว่า C เขียนขึ้นเพื่อให้ตรงกับชุดคำสั่ง PDP-7 อย่างใกล้ชิดและ PDP-11 มีการปรับแต่งอื่น ๆ จากนี้ - "ผู้คนมักจะเดาว่าพวกเขาถูกสร้างขึ้นเพื่อใช้โหมดที่อยู่เพิ่มขึ้นอัตโนมัติและลดลงอัตโนมัติที่จัดทำโดย DEC PDP-11 ซึ่ง C และ Unix ได้รับความนิยมเป็นครั้งแรกนี่เป็นเรื่องที่เป็นไปไม่ได้ในอดีต 11 เมื่อ B ได้รับการพัฒนาอย่างไรก็ตาม PDP-7 มีเซลล์หน่วยความจำที่เพิ่มขึ้นอัตโนมัติเพียงไม่กี่ตัวโดยมีคุณสมบัติที่การอ้างอิงหน่วยความจำทางอ้อมผ่านเซลล์เหล่านั้นทำให้เซลล์เพิ่มขึ้น

@Dupuplicator: ในรหัสที่ใช้จำนวนเต็มสำหรับบูลีนตัวแปรที่เพิ่มขึ้นสำหรับแต่ละ ... อะไรก็ตาม ... สามารถทำหน้าที่เป็นเคาน์เตอร์ (กี่ครั้งก็เพิ่มขึ้น) และเป็นบูลีน (มันได้รับการเพิ่มขึ้นทั้งหมดหรือ ไม่).
Keith Thompson

2

เพื่อจัดการกับรหัสดั้งเดิมที่ใช้intหรือคล้ายกันเป็นประเภทบูลีนบางส่วน


1
คำถามของฉันคือซ้ำจากที่นี่stackoverflow.com/questions/3450420/... ขอบคุณสำหรับคำตอบของคุณ
aloisdg พูดว่า Reinstate Monica

1

เพื่อทำความเข้าใจความสำคัญทางประวัติศาสตร์ของคำถามนี้คุณต้องพิจารณากรณีของ Therac-25 Therac-25 เป็นอุปกรณ์ทางการแพทย์ที่ให้รังสีแก่ผู้ป่วยมะเร็ง มันเต็มไปด้วยวิธีปฏิบัติในการเขียนโปรแกรมที่ไม่ดีซึ่งมีส่วนทำให้บันทึกความปลอดภัยไม่ดี

http://courses.cs.vt.edu/professionalism/Therac_25/Therac_1.html

(ไปที่ด้านล่างของหน้า 3)

ทุก ๆ การผ่านชุดทดสอบการตั้งค่าจะเพิ่มการตรวจสอบตำแหน่งของคอลลิเลเตอร์ด้านบนซึ่งเป็นตัวแปรที่แชร์ที่เรียกว่า Class3 ถ้า Class3 ไม่ใช่ศูนย์แสดงว่ามีความไม่สอดคล้องและไม่ควรดำเนินการต่อไป ค่าศูนย์สำหรับ Class3 บ่งชี้ว่าพารามิเตอร์ที่เกี่ยวข้องสอดคล้องกับการรักษาและลำแสงไม่ถูกยับยั้ง

...

ในระหว่างการตั้งค่าเครื่องการทดสอบการตั้งค่าจะดำเนินการหลายร้อยครั้งเนื่องจากมีการกำหนดตารางเวลาใหม่เพื่อรอให้เหตุการณ์อื่นเกิดขึ้น ในรหัสตัวแปร Class3 จะเพิ่มขึ้นทีละหนึ่งในแต่ละรอบผ่านการทดสอบการตั้งค่า เนื่องจากตัวแปร Class3 เป็น 1 ไบต์จึงสามารถมีค่าสูงสุดได้ถึง 255 ทศนิยม ดังนั้นในทุกๆ 256 ครั้งที่ผ่านรหัสการทดสอบการตั้งค่าตัวแปรจะโอเวอร์โฟลว์และมีค่าเป็นศูนย์ ซึ่งหมายความว่าในทุกๆ 256 ครั้งที่ผ่านการทดสอบการตั้งค่าตัว collimator ด้านบนจะไม่ถูกตรวจสอบและความผิดพลาด collimator ส่วนบนจะไม่ถูกตรวจจับ การเปิดรับแสงมากเกินไปเกิดขึ้นเมื่อผู้ใช้งานกดปุ่ม "set" ในช่วงเวลาที่แม่นยำที่ Class3 กลิ้งไปเป็นศูนย์ ดังนั้นจึงไม่ดำเนินการ Chkcol และ F $ mal ไม่ได้ตั้งค่าเพื่อระบุว่า collimator ด้านบนยังคงอยู่ในตำแหน่งที่มีแสงส่อง ซอฟต์แวร์เปิดใช้งานเต็ม 25 MeV โดยไม่มีเป้าหมายอยู่และไม่มีการสแกน ลำแสงอิเล็กตรอนที่มีความเข้มข้นสูงส่งผลให้กระจัดกระจายและเบี่ยงเบนโดยกระจกสแตนเลสที่อยู่ในเส้นทาง

Therac-25 บางสิ่งบางอย่างที่ใช้เช่นเทียบเท่าบนoperator++ boolอย่างไรก็ตามการเขียนโปรแกรมภาษาที่พวกเขาใช้ไม่ได้ C ++ boolและประเภทข้อมูลของพวกเขาไม่ได้ ไม่เหมือนกับการรับประกันใน C ++ อย่างไรก็ตามชนิดจำนวนเต็มปกติจะเพิ่มขึ้นเรื่อย ๆ uint8_tชนิดข้อมูลของพวกเขาคือเทียบเท่า

C ++ ตัดสินใจเก็บไว้operator++รอบ ๆ สำหรับคนที่เคยชินกับการเขียนโปรแกรมแบบนี้ แต่แทนที่จะเพิ่มค่ามันก็แค่ตั้งค่าtrueเพื่อป้องกันสิ่งต่าง ๆ เช่นนี้

โปรดทราบว่าoperator++(bool)เลิกใช้แล้ว

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

ภาคผนวก D ของ C ++ 14:

D.1 ตัวดำเนินการเพิ่มพร้อมกับตัวดำเนินการบูล
การใช้ตัวถูกดำเนินการของบูลชนิดที่มีตัวดำเนินการ ++ เลิกใช้แล้ว (ดู 5.3.2 และ 5.2.6)


ในขณะที่มันจะอธิบายว่าทำไมมันเลิกใช้มันไม่ได้อธิบายว่าทำไมมันมีอยู่ในสถานที่แรก

มันมีอยู่เพราะมีบางคนที่ตั้งค่าบูลีนโดยการเพิ่มขึ้นเมื่อการเขียนโปรแกรมใน C. C ++ ได้รับการออกแบบมาเพื่อลดการเปลี่ยนแปลงจาก C ดังนั้นพวกเขาจึงสนับสนุนด้วยboolประเภท ฉันแค่พยายามยกตัวอย่างประวัติศาสตร์เมื่อผู้คนตั้งโปรแกรมด้วยวิธีนี้
David Stone
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.