C ++: tại sao bool dài 8 bit?


132

Trong C ++, tôi tự hỏi tại sao loại bool dài 8 bit (trên hệ thống của tôi), trong đó chỉ một bit là đủ để giữ giá trị boolean?

Tôi đã từng tin rằng đó là vì lý do hiệu năng, nhưng sau đó trên máy 32 bit hoặc 64 bit, trong đó các thanh ghi rộng 32 hoặc 64 bit, lợi thế về hiệu suất là gì?

Hay đó chỉ là một trong những lý do 'lịch sử' này?


9
Một bool không phải là 8 bit trên hệ thống của tôi. Đó là 4 byte, giống như một int.
Brian Neal

21
lần trước ai đó nghĩ bạn đang nghĩ gì, chúng tôi đã kết thúc với std :: vector <bool>, "tính năng" đáng ghét nhất từng có =)
Viktor Sehr

1
jldupont, tôi nghĩ bạn đọc sai tôi. Tôi đã yêu cầu một hệ thống, ở đâu sizeof(bool)sẽ là 4. Tôi có thể thề rằng msvc có các công cụ 32 bit, nhưng tôi chỉ thử và không được.
avakar

7
Công bằng mà nói, vấn đề vector<bool>không phải là nó cố tỏ ra thông minh và đóng gói các bool thành bit, mà là nó cố gắng làm điều này và ngụy trang thành một container STL . Một bitet đơn giản sẽ ổn miễn là nó không giả vờ là một container STL.
jalf

2
@avakar - bạn có thể nhầm lẫn boolkiểu dữ liệu C ++ với BOOLkiểu Windows được nhập vào long. Vì vậy sizeof(bool) != sizeof(BOOL), điều mà tôi chắc chắn gây ra nhiều nhầm lẫn (và có thể là một số lỗi khá lớn). Đặc biệt vì cũng có booleanBOOLEANtypedefs trong Windows, đó là bí danh cho unsigned char. Ngoài ra, lưu ý rằng mặc dù thông thường boollà 1 byte, tiêu chuẩn C ++ có một lưu ý chỉ ra cụ sizeof(bool)thể có thể lớn hơn.
Michael Burr

Câu trả lời:


219

Bởi vì mọi kiểu dữ liệu C ++ phải có địa chỉ.

Làm thế nào bạn sẽ tạo một con trỏ đến một bit? Bạn không thể. Nhưng bạn có thể tạo một con trỏ tới một byte. Vì vậy, một boolean trong C ++ thường có kích thước byte. (Nó cũng có thể lớn hơn. Điều đó tùy thuộc vào việc triển khai. Điều chính là nó phải có địa chỉ, vì vậy không có kiểu dữ liệu C ++ nào có thể nhỏ hơn một byte)


7
Địa chỉ "byte" là một lựa chọn kiến ​​trúc (cấp độ hw): người ta rất có thể thiết kế một hệ thống với một "đơn vị địa chỉ" khác. Đối với các bộ xử lý thông thường, việc xử lý một "byte" dù sao cũng tìm nạp nhiều hơn một "byte" từ bộ nhớ ngoài: điều này là do lý do hiệu quả.
jldupont

8
Vâng, đó là một sự lựa chọn phần cứng và nếu phần cứng cho phép, kích thước của một bool có thể thay đổi. Nhưng OP đã hỏi tại sao một bool có chiều rộng 8 bit và trên các hệ thống trong trường hợp đó, thông thường là do CPU chỉ có thể xử lý các byte 8 bit.
jalf

2
@jldupont: Có một vài hệ thống trong đó các địa chỉ con trỏ được phân loại mịn hơn byte (tôi đã lập trình trên TI TMS34010 / 20 trước đây, sử dụng các con trỏ bit-bit), nhưng chúng hiếm khi xảy ra.
Michael Kohne

1
Không chắc chắn những gì bạn có ý nghĩa. Mọi đối tượng phải có địa chỉ, nghĩa là phải lấy được địa chỉ của một đối tượng. Đối tượng không phải lưu trữ địa chỉ của chính nó. Một char thường rộng 8 bit, đủ để lưu trữ bất kỳ 256 ký tự nào, nhưng mỗi char cũng có một địa chỉ được xác định bởi vị trí trong bộ nhớ. Đó là lý do tại sao bạn có thể tạo một con trỏ tới char.
jalf

88
Nếu tôi có thể đóng góp một sự tương tự tinh ranh: có tám tầng trong tòa nhà của tôi, nhưng Bưu điện không thừa nhận rằng chúng là các địa chỉ khác nhau. Vì vậy, nếu tôi muốn một địa chỉ cho riêng mình, thì tôi phải thuê toàn bộ tòa nhà, mặc dù tôi thực sự nằm trên một tầng. Tôi không sử dụng bảy tầng còn lại để "lưu trữ địa chỉ", tôi chỉ buộc phải lãng phí chúng vì quy tắc Bưu điện đề cập đến các tòa nhà, không phải tầng. Các đối tượng C ++ phải có một địa chỉ riêng - không có phòng đăng bài để sắp xếp thư sau khi giao hàng ;-)
Steve Jessop

39

Bộ nhớ là địa chỉ byte. Bạn không thể giải quyết một bit đơn, mà không thay đổi hoặc che dấu byte đọc từ bộ nhớ. Tôi sẽ tưởng tượng đây là một lý do rất lớn.


1
Không phải lúc nào. Chẳng hạn, MCU 8051 có 16 byte vị trí có thể định địa chỉ bit
Beached

20

Một booleanloại thường theo đơn vị bộ nhớ địa chỉ nhỏ nhất của máy đích (thường là byte 8 bit).

Quyền truy cập vào bộ nhớ luôn ở dạng "khối" (nhiều từ, đây là hiệu quả ở cấp độ phần cứng , giao dịch xe buýt): một bit boolean không thể được xử lý "một mình" trong hầu hết các hệ thống CPU. Tất nhiên, một khi dữ liệu được chứa trong một thanh ghi , thường có các hướng dẫn chuyên biệt để thao tác các bit một cách độc lập.

Vì lý do này, việc sử dụng các kỹ thuật "đóng gói bit" là khá phổ biến để tăng hiệu quả trong việc sử dụng các kiểu dữ liệu cơ sở "boolean". Một kỹ thuật như enum(trong C) với sức mạnh của 2 mã hóa là một ví dụ tốt. Loại lừa tương tự được tìm thấy trong hầu hết các ngôn ngữ.

Cập nhật : Nhờ một cuộc thảo luận tuyệt vời, tôi đã nhận thấy rằng sizeof(char)==1theo định nghĩa trong C ++. Do đó, việc định địa chỉ của kiểu dữ liệu "boolean" khá gắn với đơn vị bộ nhớ có thể định địa chỉ nhỏ nhất (củng cố quan điểm của tôi).


Đối với tất cả các ý kiến ​​bạn để lại về điều này, thật ấn tượng khi bạn bỏ qua phần quan trọng nhất của câu trả lời: Một boolloại tuân theo đơn vị bộ nhớ phân bổ nhỏ nhất vì C ++ yêu cầu phải có khả năng tạo con trỏ cho nó . Không có yêu cầu đó, một con số boolcó thể hình dung có thể được biểu diễn dưới dạng một bit ngay cả trên các máy có địa chỉ byte hiện tại.
jalf

1
hmmm ... tôi có thể tạo ra một kiến ​​trúc CPU trong đó một chút có thể định địa chỉ ... Tôi thậm chí có thể viết một trình biên dịch, vv cho nó. Tôi có thể có một vùng bộ nhớ đặc biệt (hoặc bất cứ thứ gì) có thể là "địa chỉ bit". Nó không phải là do bất kỳ sự tưởng tượng không thể.
jldupont

2
Vâng, và trên hệ thống đó, một bool có thể được tạo thành một bit đơn. Nhưng OP đã không hỏi "tại sao một bool 8 bit rộng trên CPU giả định jlduponts". Ông hỏi về các CPU hiện tại, phổ biến, hàng ngày và trên đó là vì chúng có địa chỉ byte.
jalf

4
sizeof (char) == 1 mỗi định nghĩa trong C ++, vì vậy những gì phần cứng của bạn có thể hoặc không thể làm là không liên quan. Bạn không thể có sizeof (bool) <sizeof (char). BTW C ++ được định nghĩa theo cách mà bạn có thể có con trỏ "béo" để giải quyết một số tiểu đơn vị của phần cứng có thể giải quyết nếu không thuận tiện để có đơn vị địa chỉ phần cứng nhỏ nhất. Điều này đã được sử dụng ít nhất trong một số trình biên dịch C cho các kiến ​​trúc địa chỉ từ cũ.
Lập trình viên

@AProgrammer :: sizeof(char)==1 definitionđó là đối số tốt nhất cho lập luận của tôi. Cảm ơn!
jldupont

6

Các câu trả lời về 8 bit là dung lượng bộ nhớ nhỏ nhất có thể định địa chỉ là chính xác. Tuy nhiên, theo một cách nào đó , một số ngôn ngữ có thể sử dụng 1 bit cho booleans. Tôi dường như nhớ các bộ triển khai Pascal dưới dạng các chuỗi bit. Đó là, cho các bộ sau:

{1, 2, 5, 7}

Bạn có thể có điều này trong bộ nhớ:

01100101

Tất nhiên, bạn có thể làm một cái gì đó tương tự trong C / C ++ nếu bạn muốn. (Nếu bạn đang theo dõi một loạt các booleans, điều đó có thể có ý nghĩa, nhưng nó thực sự phụ thuộc vào tình huống.)


8
Trên thực tế, C ++ thực hiện điều này với vectơ chứa chuyên dụng <bool> - nó thường được xem là một thảm họa.

C ++ cũng thực hiện điều này với "trường bit", được kế thừa từ C. Khi khai báo biến thành viên của struct / class, bạn có thể khai báo số bit được sử dụng để lưu trữ giá trị (ví dụ: "trường ngắn không dấu: 3").

@Neil: tại sao nó thường được xem là một thảm họa? Nó có phải là một vấn đề hiệu suất?
Jérôme

2
@Jerome: Đó là bởi vì, vì một chút không thể xử lý được, nên nó không thể hoạt động theo cách thông thường vector. Nó không thực sự là một loại container STL, bởi vì có các ràng buộc về hành vi. Điều tồi tệ hơn là nó gây ra vấn đề với ai đó có bools và muốn tạo ra một vectortrong số họ. Đó là hành vi đáng ngạc nhiên, và đó không phải là điều bạn muốn trong một ngôn ngữ.
David Thornley

1
@jldupont - đủ để tạo một điểm như thế này một lần. Và C ++ không đảm bảo rằng các bit có thể đánh địa chỉ (thay vì ngược lại), bất kể phần cứng có khả năng gì.

1

Tôi biết điều này đã cũ nhưng tôi nghĩ tôi sẽ ném 2 xu của mình.

Nếu bạn giới hạn kiểu boolean hoặc dữ liệu của mình ở một bit thì ứng dụng của bạn có nguy cơ bị dòng bộ nhớ. Làm thế nào để bạn xử lý các số liệu thống kê lỗi trong bộ nhớ chỉ dài một bit?

Tôi đã đi phỏng vấn xin việc và một trong những tuyên bố mà người dẫn chương trình nói với tôi là: "Khi chúng tôi gửi tín hiệu để phóng tên lửa, chúng tôi chỉ gửi một bit đơn giản qua bit không dây. Gửi một bit là cực nhanh và chúng tôi cần tín hiệu đó càng nhanh càng tốt. "

Vâng, đó là một thử nghiệm để xem liệu tôi có hiểu các khái niệm và bit, byte và xử lý lỗi không. Làm thế nào dễ dàng cho một kẻ xấu gửi một tin nhắn một bit. Hoặc điều gì xảy ra nếu trong quá trình truyền, bit bị lật theo cách khác.


Đặt câu hỏi mới , không đăng câu hỏi của bạn dưới dạng câu trả lời cho các câu hỏi khác.
Igor Jerosimić

6
Tôi nghĩ rằng câu hỏi trong "câu trả lời" này thực sự là một câu hỏi tu từ, tức là lý do chúng tôi không triển khai booleans như một bit là vì một bit không thể xử lý các số liệu thống kê lỗi.
Stephen Holt

1
@StephenHolt nhưng đó không phải là lý do và TBH câu trả lời này không có ý nghĩa gì.
doc

1
...gì? Tôi không biết ý của bạn là gì bởi "số liệu thống kê lỗi", cho dù CRC hay tương tự hay đại diện bẫy. Nhưng trong mọi trường hợp, ngay cả các loại lớn hơn cũng không sử dụng các bit 'phụ tùng' bổ sung cho "thống kê lỗi" vì tất cả các lập trình viên môi trường cực đoan đều cho rằng phần cứng của họ có thể xử lý phát hiện / sửa lỗi trước khi mã của họ đọc được bộ nhớ, vì vậy họ không cần dành thời gian của họ bằng cách nào đó đệm mọi biến với thông tin xác minh hoặc bất cứ điều gì. Đó không phải là lý do tại sao boolsử dụng 8 bit trên máy của OP và 32 bit của tôi, vì 7 hoặc 31 bit khác đó chắc chắn không được sử dụng cho bất kỳ "thống kê lỗi" nào. Điều này vô nghĩa
gạch dưới

1

Một số trình biên dịch nhúng có loại int1 được sử dụng để đóng gói các cờ boolean bit (ví dụ: trình biên dịch C của CCS cho Microchip MPU's). Thiết lập, xóa và kiểm tra các biến này sử dụng các lệnh cấp bit đơn hướng dẫn, nhưng trình biên dịch sẽ không cho phép bất kỳ hoạt động nào khác (ví dụ: lấy địa chỉ của biến), vì các lý do được ghi trong các câu trả lời khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.