C ++: ทำไมบูลถึงยาว 8 บิต?


132

ใน C ++ ฉันสงสัยว่าทำไมประเภทบูลถึงมีความยาว 8 บิต (ในระบบของฉัน) ซึ่งมีเพียงบิตเดียวเท่านั้นที่จะเก็บค่าบูลีนได้?

ฉันเคยเชื่อว่าเป็นเพราะเหตุผลด้านประสิทธิภาพ แต่ในเครื่อง 32 บิตหรือ 64 บิตที่รีจิสเตอร์กว้าง 32 หรือ 64 บิตข้อดีด้านประสิทธิภาพคืออะไร?

หรือเป็นเพียงหนึ่งในเหตุผลทางประวัติศาสตร์เหล่านี้?


9
บูลไม่ใช่ 8 บิตในระบบของฉัน มันคือ 4 ไบต์เหมือนกับ int
Brian Neal

21
ครั้งสุดท้ายที่มีคนคิดว่าคุณกำลังคิดอะไรเราปิดท้ายด้วย std :: vector <bool> ซึ่งเป็น "คุณลักษณะ" ที่เกลียดที่สุดเท่าที่เคยมีมา =)
Viktor Sehr

1
jldupont ฉันคิดว่าคุณอ่านผิด ฉันกำลังขอระบบที่ไหนsizeof(bool)จะเป็น 4 ฉันสาบานได้ว่า msvc มีบูล 32 บิต แต่ฉันลองแล้วมันไม่เป็นเช่นนั้น
avakar

7
เพื่อความเป็นธรรมปัญหากับvector<bool>ไม่ได้ว่ามันพยายามที่จะฉลาดและแพ็ค bools เป็นบิต แต่ก็พยายามที่จะทำเช่นนี้และปลอมตัวเป็นภาชนะ STL บิตเซ็ตธรรมดาจะใช้ได้ดีตราบเท่าที่ไม่ได้แสร้งทำเป็นว่าเป็นคอนเทนเนอร์ STL
jalf

2
@avakar - คุณอาจจะทำให้เกิดความสับสน c ++ boolชนิดข้อมูลกับของ Windows BOOLชนิดซึ่งเป็น typedefed longไป ดังนั้นsizeof(bool) != sizeof(BOOL)ซึ่งฉันแน่ใจว่าทำให้เกิดความสับสนอย่างมาก (และอาจเป็นข้อบกพร่องจำนวนมาก) โดยเฉพาะอย่างยิ่งเนื่องจากยังมีbooleanและBOOLEANtypedef ใน Windows ซึ่งเป็นนามแฝงสำหรับunsigned char. นอกจากนี้โปรดทราบว่าแม้ว่าโดยทั่วไปboolจะมีขนาด 1 ไบต์ แต่มาตรฐาน C ++ ก็มีหมายเหตุที่ระบุโดยเฉพาะว่าsizeof(bool)สามารถมีขนาดใหญ่กว่าได้
Michael Burr

คำตอบ:


219

เนื่องจากข้อมูล C ++ ทุกชนิดต้องระบุแอดเดรสได้

คุณจะสร้างตัวชี้เป็นบิตเดียวได้อย่างไร? คุณทำไม่ได้ แต่คุณสามารถสร้างตัวชี้เป็นไบต์ได้ ดังนั้นบูลีนใน C ++ มักมีขนาดไบต์ (อาจมีขนาดใหญ่ขึ้นด้วยทั้งนี้ขึ้นอยู่กับการนำไปใช้งานหลัก ๆ คือต้องระบุแอดเดรสได้ดังนั้นจึงไม่มีประเภทข้อมูล C ++ ที่เล็กกว่าไบต์ได้)


7
การกำหนดแอดเดรส "ไบต์" เป็นทางเลือกทางสถาปัตยกรรม (ระดับ hw): หนึ่งสามารถออกแบบระบบด้วย "หน่วยการระบุแอดเดรส" ที่แตกต่างกันได้เป็นอย่างดี สำหรับโปรเซสเซอร์ทั่วไปการระบุ "ไบต์" ลงท้ายด้วยการดึงข้อมูลจากหน่วยความจำภายนอกมากกว่า "ไบต์": นี่เป็นเพราะเหตุผลด้านประสิทธิภาพ
jldupont

8
ใช่เป็นตัวเลือกฮาร์ดแวร์และหากฮาร์ดแวร์อนุญาตขนาดของบูลก็อาจเปลี่ยนไป แต่ OP ถามว่าทำไมบูลถึงกว้าง 8 บิตและในระบบที่เป็นเช่นนั้นโดยทั่วไปเป็นเพราะ CPU สามารถระบุไบต์ 8 บิตเท่านั้น
jalf

2
@jldupont: มีระบบบางระบบที่ที่อยู่ของตัวชี้มีความละเอียดอ่อนกว่าไบต์ (ฉันเคยตั้งโปรแกรมไว้ใน TI TMS34010 / 20 รุ่นเก่าก่อนหน้านี้ซึ่งใช้ตัวชี้แบบบิต) แต่ก็หายากมาก
ไมเคิลโคห์น

1
ไม่แน่ใจคุณหมายถึงอะไร. ทุกออบเจ็กต์ต้องสามารถระบุแอดเดรสได้นั่นคือต้องสามารถดึงแอดเดรสของอ็อบเจ็กต์ได้ วัตถุไม่จำเป็นต้องจัดเก็บที่อยู่ของตัวเอง โดยทั่วไปแล้ว char จะมีความกว้าง 8 บิตเพียงพอที่จะจัดเก็บอักขระ 256 ตัว แต่แต่ละ char ยังมีที่อยู่ที่กำหนดโดยตำแหน่งในหน่วยความจำ นั่นคือเหตุผลที่คุณสามารถสร้างตัวชี้ไปยังถ่านได้
jalf

88
ถ้าฉันอาจมีส่วนช่วยในการเปรียบเทียบแบบหลบ ๆ ซ่อน ๆ : มีแปดชั้นในอาคารของฉัน แต่ที่ทำการไปรษณีย์ไม่รับทราบว่าเป็นที่อยู่ที่แตกต่างกัน ดังนั้นถ้าฉันต้องการที่อยู่ทั้งหมดเป็นของตัวเองฉันก็ต้องเช่าทั้งตึกแม้ว่าฉันจะพอดีกับชั้นเดียวก็ตาม ฉันไม่ได้ใช้อีกเจ็ดชั้นในการ "จัดเก็บที่อยู่" ฉันแค่บังคับให้เสียมันไปเพราะกฎของที่ทำการไปรษณีย์ที่ที่อยู่หมายถึงอาคารไม่ใช่ชั้น วัตถุ C ++ ต้องมีที่อยู่เป็นของตัวเอง - ไม่มีห้องโพสต์เพื่อจัดเรียงจดหมายหลังการจัดส่ง ;-)
Steve Jessop

39

หน่วยความจำเป็นไบต์แอดเดรสได้ คุณไม่สามารถระบุบิตเดียวโดยไม่ขยับหรือกำบังไบต์ที่อ่านจากหน่วยความจำ ฉันคิดว่านี่เป็นเหตุผลที่ยิ่งใหญ่มาก


1
ไม่เสมอ. ตัวอย่างเช่น 8051 MCU มีตำแหน่งแอดเดรสบิต 16 ไบต์
Beached

20

booleanประเภทตามปกติต่อไปนี้หน่วยที่เล็กที่สุดของหน่วยความจำแอดเดรสของเครื่องเป้าหมาย (เช่นมักจะ 8bits ไบต์)

การเข้าถึงหน่วยความจำจะอยู่ในรูป "ชิ้น" เสมอ (มีหลายคำซึ่งมีไว้เพื่อประสิทธิภาพในระดับฮาร์ดแวร์ธุรกรรมบัส): บิตบูลีนไม่สามารถระบุ "เพียงอย่างเดียว" ในระบบ CPU ส่วนใหญ่ แน่นอนว่าเมื่อข้อมูลอยู่ในรีจิสเตอร์แล้วมักจะมีคำสั่งพิเศษในการจัดการบิตอย่างอิสระ

ด้วยเหตุนี้จึงเป็นเรื่องปกติที่จะใช้เทคนิค"การบรรจุบิต"เพื่อเพิ่มประสิทธิภาพในการใช้ชนิดข้อมูลฐาน "บูลีน" เทคนิคเช่นenum(ใน C) ที่มีกำลัง 2 การเข้ารหัสเป็นตัวอย่างที่ดี เคล็ดลับประเภทเดียวกันนี้พบได้ในภาษาส่วนใหญ่

อัปเดต : ขอบคุณการสนทนาที่ยอดเยี่ยมทำให้ฉันได้รับความสนใจsizeof(char)==1ตามคำจำกัดความใน C ++ ดังนั้นการระบุประเภทข้อมูล "บูลีน" จึงค่อนข้างเชื่อมโยงกับหน่วยความจำแอดเดรสหน่วยที่เล็กที่สุด (ช่วยเสริมประเด็นของฉัน)


สำหรับทุกความคิดเห็นที่คุณทิ้งไว้เกี่ยวกับเรื่องนี้มันเป็นเรื่องที่น่าประทับใจที่คุณซ้ายออกส่วนที่สำคัญที่สุดของคำตอบ: เป็นboolประเภทดังนี้หน่วยที่เล็กที่สุดของหน่วยความจำ allocatable เพราะ c ++ ต้องว่ามันต้องเป็นไปได้ในการสร้างตัวชี้ไปยัง หากไม่มีข้อกำหนดนั้นboolอาจมีการแสดงเป็นบิตเดียวได้แม้ในเครื่องที่ระบุไบต์ปัจจุบัน
jalf

1
อืม ... ฉันสามารถสร้างสถาปัตยกรรมซีพียูที่สามารถระบุแอดเดรสได้เล็กน้อย ... ฉันสามารถเขียนคอมไพเลอร์ ฯลฯ สำหรับมันได้ ฉันสามารถมีพื้นที่พิเศษของหน่วยความจำ (หรืออะไรก็ได้) ที่ "บิตแอดเดรสได้" มันไม่ได้เป็นไปไม่ได้ด้วยจินตนาการใด ๆ
jldupont

2
ใช่และในระบบนั้นบูลสามารถทำให้เป็นบิตเดียวได้ แต่ OP ไม่ได้ถามว่า "ทำไม bool 8 bits wide บน jlduponts hypothetical CPU" เขาถามเกี่ยวกับซีพียูในปัจจุบันที่ใช้กันทั่วไปในชีวิตประจำวันและเกี่ยวกับซีพียูเหล่านี้เป็นเพราะพวกมันสามารถแอดเดรสแบบไบต์ได้
jalf

4
sizeof (ถ่าน) == 1 ต่อคำจำกัดความใน C ++ ดังนั้นสิ่งที่ฮาร์ดแวร์ของคุณทำได้หรือไม่สามารถทำได้ไม่เกี่ยวข้อง คุณไม่สามารถมี sizeof (บูล) <sizeof (ถ่าน) BTW C ++ ถูกกำหนดในลักษณะที่คุณสามารถมีตัวชี้ "fat" เพื่อระบุหน่วยย่อยบางส่วนของสิ่งที่ฮาร์ดแวร์สามารถจัดการได้หากไม่สะดวกที่จะให้ char เป็นหน่วยแอดเดรสฮาร์ดแวร์ที่เล็กที่สุด สิ่งนี้ถูกใช้อย่างน้อยในคอมไพเลอร์ C บางตัวสำหรับสถาปัตยกรรมที่ระบุแอดเดรสคำเก่า
AProgrammer

@AProgrammer: sizeof(char)==1 definitionนั่นเป็นข้อโต้แย้งที่ดีที่สุดสำหรับการโต้แย้งของฉัน ขอบคุณ!
jldupont

6

คำตอบเกี่ยวกับ 8 บิตคือหน่วยความจำจำนวนน้อยที่สุดที่แอดเดรสได้นั้นถูกต้อง อย่างไรก็ตามบางภาษาสามารถใช้ 1 บิตสำหรับบูลีนได้ ฉันดูเหมือนจะจำชุดการใช้งาน Pascal เป็นสตริงบิตได้ นั่นคือสำหรับชุดต่อไปนี้:

{1, 2, 5, 7}

คุณอาจมีสิ่งนี้อยู่ในความทรงจำ:

01100101

แน่นอนคุณสามารถทำสิ่งที่คล้ายกันใน C / C ++ ได้หากต้องการ (หากคุณติดตามบูลีนจำนวนมากมันอาจสมเหตุสมผล แต่มันขึ้นอยู่กับสถานการณ์จริงๆ)


8
ในความเป็นจริง C ++ ทำสิ่งนี้กับเวกเตอร์คอนเทนเนอร์พิเศษ <bool> ซึ่งมักถูกมองว่าเป็นภัยพิบัติ

C ++ ทำเช่นนี้กับ "bit fields" ซึ่งสืบทอดมาจาก C เมื่อประกาศตัวแปรสมาชิกของโครงสร้าง / คลาสคุณสามารถประกาศจำนวนบิตที่ใช้เก็บค่าได้ (เช่น "เขตข้อมูลสั้นที่ไม่ได้ลงนาม: 3")

@ นีล: ทำไมถึงถูกมองว่าเป็นภัยพิบัติ? เป็นปัญหาด้านประสิทธิภาพหรือไม่?
Jérôme

2
@Jerome: vectorก็เพราะตั้งแต่บิตไม่แอดเดรสก็ไม่สามารถทำงานในลักษณะเป็นปกติ ไม่ใช่คอนเทนเนอร์ประเภท STL เนื่องจากมีข้อ จำกัด เกี่ยวกับลักษณะการทำงาน สิ่งที่แย่กว่านั้นคือมันทำให้เกิดปัญหากับคนที่มีboolและต้องการสร้างvectorมันขึ้นมา เป็นพฤติกรรมที่น่าประหลาดใจและนั่นไม่ใช่สิ่งที่คุณต้องการในภาษา
David Thornley

1
@jldupont - เพียงพอที่จะทำให้ประเด็นเช่นนี้ครั้งเดียว และ C ++ ไม่รับประกันว่าบิตสามารถระบุแอดเดรสได้ (แทนที่จะเป็นแบบย้อนกลับ) ไม่ว่าฮาร์ดแวร์จะมีความสามารถอะไรก็ตาม

1

ฉันรู้ว่ามันเก่า แต่ฉันคิดว่าฉันทุ่ม 2 เซ็นต์

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

ฉันไปสัมภาษณ์งานและหนึ่งในข้อความที่หัวหน้าโครงการพูดกับฉันคือ "เมื่อเราส่งสัญญาณเพื่อเปิดตัว missle เราเพียงแค่ส่งบิตหนึ่งบิตแบบง่ายๆผ่านทางระบบไร้สายการส่งหนึ่งบิตนั้นเร็วมากและเรา ต้องการให้สัญญาณนั้นเร็วที่สุด”

เป็นการทดสอบเพื่อดูว่าฉันเข้าใจแนวคิดและบิตไบต์และการจัดการข้อผิดพลาดหรือไม่ มันง่ายแค่ไหนที่คนเลวจะส่งข้อความเพียงเล็กน้อย หรือจะเกิดอะไรขึ้นถ้าในระหว่างการส่งบิตถูกพลิกไปอีกทาง


ถามคำถามใหม่อย่าโพสต์คำถามของคุณเป็นคำตอบสำหรับคำถามอื่น ๆ
Igor Jerosimić

6
ฉันคิดว่าคำถามที่มีอยู่ใน "คำตอบ" นี้เป็นเรื่องเกี่ยวกับวาทศิลป์กล่าวคือเหตุผลที่เราไม่ใช้บูลีนเป็นบิตเนื่องจากบิตเดียวไม่สามารถจัดการกับสถิติข้อผิดพลาดได้
Stephen Holt

1
@StephenHolt แต่นั่นไม่ใช่เหตุผลและ TBH คำตอบนี้ไม่สมเหตุสมผล
doc

1
...อะไร? ฉันไม่รู้ว่า "สถิติข้อผิดพลาด" หมายถึงอะไรไม่ว่าจะเป็น CRC หรือสิ่งที่ชอบหรือการแสดงกับดัก แต่ไม่ว่าในกรณีใดแม้แต่ประเภทที่ใหญ่กว่าก็ไม่ได้ใช้บิต 'สำรอง' พิเศษสำหรับ "สถิติข้อผิดพลาด" เนื่องจากผู้เขียนโค้ดในสภาพแวดล้อมที่รุนแรงถือว่าฮาร์ดแวร์ของพวกเขาสามารถจัดการกับการตรวจจับ / แก้ไขข้อผิดพลาดได้ก่อนที่โค้ดของพวกเขาจะอ่านหน่วยความจำดังนั้นพวกเขา ไม่จำเป็นต้องใช้เวลาในการเติมตัวแปรทุกตัวด้วยข้อมูลการยืนยันหรืออะไรก็ตาม นั่นไม่ใช่เหตุผลที่boolใช้ 8 บิตบนเครื่องของ OP และ 32 ในของฉันเนื่องจาก 7 หรือ 31 บิตอื่น ๆ นั้นไม่ได้ใช้สำหรับ "สถิติข้อผิดพลาด" ใด ๆ สิ่งนี้ไม่สมเหตุสมผล
underscore_d

1

คอมไพเลอร์แบบฝังบางตัวมีประเภท int1 ที่ใช้สำหรับแฟล็กบูลีนแบบบิตแพ็ค (เช่นซีรีส์ CCS ของคอมไพเลอร์ C สำหรับ Microchip MPU) การตั้งค่าการล้างและการทดสอบตัวแปรเหล่านี้ใช้คำสั่งระดับบิตคำสั่งเดี่ยว แต่คอมไพเลอร์จะไม่อนุญาตให้ดำเนินการอื่นใด (เช่นการใช้ที่อยู่ของตัวแปร) ด้วยเหตุผลที่ระบุไว้ในคำตอบอื่น ๆ

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