Tại sao boolean 1 byte mà không phải 1 bit kích thước?


127

Trong C ++,

  • Tại sao boolean 1 byte mà không phải 1 bit kích thước?
  • Tại sao không có các loại như số nguyên 4 bit hoặc 2 bit?

Tôi đang bỏ lỡ những điều trên khi viết trình giả lập cho CPU


10
Trong C ++, bạn có thể "đóng gói" dữ liệu bằng cách sử dụng các trường bit. struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. Hầu hết các trình biên dịch sẽ phân bổ đầy đủ unsigned int, tuy nhiên chúng tự xử lý việc xoay vòng bit khi bạn đọc / ghi. Ngoài ra, họ tự giải quyết với các hoạt động modulo. Đó là một unsigned small : 4thuộc tính có giá trị từ 0 đến 15 và khi cần đến 16, nó sẽ không ghi đè lên bit trước đó :)
Matthieu M.

Câu trả lời:


208

Bởi vì CPU không thể giải quyết bất cứ điều gì nhỏ hơn một byte.


10
Chết tiệt, bây giờ thật là khó xử thưa ngài
Asm

31
Trên thực tế, bốn x86 hướng dẫn bt, bts, btrbtc có thể giải quyết bit duy nhất!
dòng chảy

11
Tôi nghĩ rằng btđịa chỉ một byte bù và sau đó kiểm tra bit ở một độ lệch cho trước, bất kể khi chỉ định một địa chỉ bạn đi theo byte ... bit offset bit sẽ có một chút dài dòng (xin lỗi chơi chữ).
dùng7116

2
@six: Bạn có thể tải phần đầu của một mảng trong một thanh ghi và sau đó "bit offset" tương đối thành một giây. Độ lệch bit không bị giới hạn ở "trong một byte", nó có thể là bất kỳ số 32 bit nào.
fredoverflow

4
Vâng, có và không. Chúng ta có bitfield và chúng ta có thể có một con trỏ bitfield, đó là địa chỉ + số bit. Rõ ràng, một con trỏ như vậy sẽ không thể chuyển đổi thành void * vì yêu cầu lưu trữ thêm cho số bit.
Maxim Egorushkin

32

Từ Wikipedia :

Trong lịch sử, một byte là số bit được sử dụng để mã hóa một ký tự văn bản trong máy tính và vì lý do này là yếu tố địa chỉ cơ bản trong nhiều kiến ​​trúc máy tính.

Vì vậy, byte là các đơn vị địa chỉ cơ bản , dưới đây mà kiến trúc máy tính không thể địa chỉ. Và vì không có (có thể) tồn tại các máy tính hỗ trợ byte 4 bit, nên bạn không có 4 bit, bool v.v.

Tuy nhiên, nếu bạn có thể thiết kế một kiến ​​trúc như vậy có thể giải quyết 4 bit là đơn vị địa chỉ cơ bản, thì bạn sẽ chỉ có boolkích thước 4 bit, trên máy tính đó!


4
"bạn sẽ chỉ có kích thước 4 bit, chỉ trên máy tính đó" - không bạn sẽ không, vì tiêu chuẩn cấm CHAR_BIT nhỏ hơn 8. Nếu đơn vị có thể đánh địa chỉ trên kiến ​​trúc nhỏ hơn 8 bit, thì a Việc triển khai C ++ sẽ chỉ phải trình bày một mô hình bộ nhớ khác với mô hình bộ nhớ của phần cứng cơ bản.
Steve Jessop

@Steve: Rất tiếc ... Tôi đã bỏ qua điều đó. Đã xóa intcharkhỏi bài viết của tôi.
Nawaz

1
bạn cũng không thể có 4 bit bool, vì đây charlà đơn vị địa chỉ nhỏ nhất trong C ++ , bất kể kiến ​​trúc có thể xử lý những gì với các opcode riêng của nó. sizeof(bool)phải có giá trị ít nhất là 1 và các boolđối tượng liền kề phải có địa chỉ riêng trong C ++ , vì vậy việc triển khai chỉ cần làm cho chúng lớn hơn và lãng phí bộ nhớ. Đó là lý do tại sao các trường bit tồn tại như một trường hợp đặc biệt: các thành viên bitfield của một cấu trúc không bắt buộc phải có địa chỉ riêng biệt, vì vậy chúng có thể nhỏ hơn một char(mặc dù toàn bộ cấu trúc vẫn không thể).
Steve Jessop

@ Steve Jessop: điều đó có vẻ thú vị. bạn có thể vui lòng cho tôi tham khảo từ đặc tả ngôn ngữ nơi nó nói charlà đơn vị địa chỉ nhỏ nhất trong C ++ không?
Nawaz

3
Câu lệnh cụ thể gần nhất có lẽ là 3.9 / 4: "Biểu diễn đối tượng của một đối tượng loại T là chuỗi các đối tượng char không dấu được lấy bởi đối tượng của loại T, trong đó N bằng sizeof (T)". Rõ ràng sizeof(bool)không thể là 0,5 :-) Tôi cho rằng việc triển khai có thể cung cấp hợp pháp các con trỏ byte phụ như một phần mở rộng, nhưng các đối tượng "thông thường" như bool, được phân bổ theo cách thông thường, phải thực hiện những gì tiêu chuẩn nói.
Steve Jessop

12

Câu trả lời dễ nhất là; đó là vì CPU xử lý bộ nhớ theo byte chứ không phải theo bit và hoạt động theo bit rất chậm.

Tuy nhiên, có thể sử dụng phân bổ kích thước bit trong C ++. Có std :: vector chuyên môn hóa cho các vectơ bit, và cũng có các cấu trúc lấy các mục có kích thước bit.


1
Không chắc chắn tôi sẽ đồng ý rằng các hoạt động bitwise là chậm. ands, nots, xors vv rất nhanh. Nó thường là việc thực hiện các hoạt động bitwise chậm. Ở cấp độ máy họ khá nhanh. Phân nhánh ... bây giờ thì chậm.
Hogan

3
Để làm cho nó rõ ràng hơn, nếu bạn tạo một vectơ booleans và đặt 24 booleans vào nó, nó sẽ chỉ mất 3 byte (3 * 8). Nếu bạn đặt một boolean khác vào, nó sẽ mất một byte khác. Tuy nhiên, nếu bạn đẩy một boolean khác, nó sẽ không mất thêm byte nào vì nó sử dụng các bit "miễn phí" trong byte cuối cùng
Pedro Loureiro

vâng, tôi cũng nghi ngờ các hoạt động bitewise là chậm :)
Pedro Loureiro

Các vectơ bit không tạo ra phân bổ kích thước bit. chúng tạo ra các phân bổ có kích thước byte. Không thể phân bổ một bit.
John Dibling

1
Đọc một bit đơn trong một vectơ bit đòi hỏi ba thao tác: shift và một lần nữa. Viết là hai. Trong khi các byte riêng lẻ có thể được truy cập bằng một cái duy nhất.
sukru

7

Quay trở lại những ngày xưa khi tôi phải đi bộ đến trường trong một trận bão tuyết dữ dội, khó khăn cả hai chiều và bữa trưa là bất cứ con vật nào chúng ta có thể theo dõi trong khu rừng phía sau trường và giết chết bằng tay không, máy tính có bộ nhớ ít hơn nhiều so với hôm nay. Máy tính đầu tiên tôi từng sử dụng có 6K RAM. Không phải 6 megabyte, không phải 6 gigabyte, 6 kilobyte. Trong môi trường đó, sẽ rất có ý nghĩa khi đóng gói càng nhiều booleans vào một int như bạn có thể, và vì vậy chúng tôi sẽ thường xuyên sử dụng các hoạt động để đưa chúng ra và đưa chúng vào.

Ngày nay, khi mọi người sẽ chế giễu bạn vì chỉ có 1 GB RAM và nơi duy nhất bạn có thể tìm thấy một ổ cứng có dưới 200 GB là tại một cửa hàng đồ cổ, thật không đáng để bận tâm đến việc đóng gói bit.


Ngoại trừ khi giao dịch với Cờ. Những thứ như Thiết lập nhiều tùy chọn trên một cái gì đó ... ví dụ. 00000001 + 00000100 = 00000101.
Armstrongest

@Atomix: Tôi gần như không bao giờ làm điều này nữa. Nếu tôi cần hai cờ, tôi tạo hai trường boolean. Tôi đã từng viết mã nơi tôi đóng gói các cờ như thế và sau đó viết "if flags & 0x110! = 0 then" hoặc tương tự, nhưng đây là mật mã và ngày nay tôi thường tạo các trường riêng biệt và viết "if fooFlag || barFlag " thay thế. Tôi sẽ không loại trừ khả năng các trường hợp trong đó việc đóng gói các cờ như thế tốt hơn vì một số lý do, nhưng không còn cần thiết phải lưu bộ nhớ như trước đây.
Jay

2
Trên thực tế, việc bạn đóng gói bit là khá đáng, nếu bạn muốn tính toán của mình nhanh - với lượng dữ liệu lớn mà bạn lưu trữ trong bộ nhớ. Booleans đóng gói không chỉ dành cho lưu trữ nhỏ hơn - điều đó có nghĩa là bạn có thể đọc các mảng đầu vào boolean của mình nhanh hơn 8 lần (về mặt băng thông) như khi chúng được giải nén và điều đó thường khá quan trọng. Ngoài ra, bạn có thể sử dụng các hoạt động bit, như popc (số lượng dân số) để tăng tốc công việc của bạn trên chính CPU.
einpoklum

2
Số lượng booleans thực sự khổng lồ là những gì bạn làm việc mỗi ngày nếu bạn làm: DBMSes, học máy, mô phỏng khoa học và một loạt các thứ khác. Và - chỉ làm việc với chúng có nghĩa là sao chép chúng - từ bộ nhớ vào bộ đệm. Một triệu bool là không có gì, nghĩ rằng hàng tỷ.
einpoklum

1
@PeterCordes Vâng, hoàn toàn, nếu tôi có một bộ booleans hợp lý là "cùng một ý tưởng" để tôi tự nhiên nghĩ về chúng như một "mảng" theo nghĩa nào đó, và nếu sau đó tôi sẽ che dấu hoặc lọc chúng hoặc mặt khác thực hiện các thao tác bitwise trên chúng, sau đó đóng gói chúng thành byte có thể có ý nghĩa tốt. Như tôi đã nói trước đó, tôi rất khó nghĩ về lần cuối cùng tôi làm việc trên một ứng dụng áp dụng các điều kiện đó, nhưng bạn đưa ra một vài ví dụ hay và tôi chắc chắn với một chút trí tưởng tượng mà người ta có thể nghĩ về người khác.
Jay

6

Bạn có thể có các bit 1 bit và int 4 và 2 bit. Nhưng điều đó sẽ làm cho một tập lệnh kỳ lạ không tăng hiệu suất vì đó là một cách không tự nhiên để nhìn vào kiến ​​trúc. Nó thực sự có ý nghĩa để "lãng phí" một phần tốt hơn của một byte thay vì cố gắng lấy lại dữ liệu không sử dụng.

Theo kinh nghiệm của tôi, ứng dụng duy nhất làm phiền nhiều gói thành một byte duy nhất là Sql Server.


5

Bạn có thể sử dụng các trường bit để lấy số nguyên có kích thước phụ.

struct X
{
    int   val:4;   // 4 bit int.
};

Mặc dù nó thường được sử dụng để ánh xạ các cấu trúc thành các mẫu bit dự kiến ​​phần cứng chính xác:

struct SomThing   // 1 byte value (on a system where 8 bits is a byte
{
    int   p1:4;   // 4 bit field
    int   p2:3;   // 3 bit field
    int   p3:1;   // 1 bit
};

5

Bởi vì một byte là đơn vị địa chỉ nhỏ nhất trong ngôn ngữ.

Nhưng bạn có thể làm bool mất 1 bit chẳng hạn nếu bạn có một loạt chúng, vd. trong một cấu trúc, như thế này:

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};

2

boolcó thể là một byte - kích thước địa chỉ nhỏ nhất của CPU hoặc có thể lớn hơn. Nó không phải là bất thường để có boolkích thước intcho mục đích hiệu suất. Nếu cho các mục đích cụ thể (giả sử mô phỏng phần cứng) bạn cần một loại có N bit, bạn có thể tìm một thư viện cho điều đó (ví dụ thư viện GBL có BitSet<N>lớp). Nếu bạn quan tâm đến kích thước của bool(bạn có thể có một thùng chứa lớn), thì bạn có thể tự đóng gói các bit hoặc sử dụng std::vector<bool>nó sẽ giúp bạn (hãy cẩn thận với cái sau, vì nó không thỏa mãn các yêu cầu của container).


2

Hãy suy nghĩ về cách bạn sẽ thực hiện điều này ở cấp trình giả lập của bạn ...

bool a[10] = {false};

bool &rbool = a[3];
bool *pbool = a + 3;

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);

2

Bởi vì nói chung, CPU phân bổ bộ nhớ với 1 byte làm đơn vị cơ bản, mặc dù một số CPU như MIPS sử dụng từ 4 byte.

Tuy nhiên, vectorgiao dịch booltheo cách đặc biệt, với vector<bool>một bit cho mỗi bool được phân bổ.


1
Tôi tin rằng ngay cả cpu MIPS sẽ cung cấp cho bạn quyền truy cập vào một byte riêng lẻ, mặc dù có một hình phạt về hiệu năng.
Paul Tomblin

@Paul: Có bạn đúng, nhưng nói chung là từ cụ thể lw/ swđược sử dụng rộng rãi hơn nhiều.
Ryan Li

Không biết về MIPS, nhưng kiến ​​trúc IA-64 chỉ cho phép truy cập trên ranh giới 64 bit.
Gene Bushuyev

0

Byte là đơn vị lưu trữ dữ liệu số nhỏ hơn của máy tính. Trong máy tính, RAM có hàng triệu byte và bất kỳ ai trong số họ cũng có địa chỉ. Nếu nó có một địa chỉ cho mỗi bit, một máy tính có thể quản lý RAM ít hơn 8 lần so với những gì nó có thể.

Thêm thông tin: Wikipedia


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.