2013-09-04 34 views
6

Ví dụ:Trình biên dịch xác định kích thước của cấu trúc bitfield như thế nào?

struct a { 
    uint32_t foreColor_ : 32; 
    uint32_t backColor_ : 32; 
    uint16_t lfHeight_ : 16; 
    uint16_t flags_: 4; 
    bool lfBold_: 1; 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; 
}; 

là 16 byte nhưng

struct a { 
    uint32_t foreColor_ : 32; 
    uint32_t backColor_ : 32; 
    uint16_t lfHeight_ : 16; 
    uint8_t  flags_: 4; 
    bool lfBold_: 1; 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; //for ime 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; 
}; 

dài 12 byte.

Tôi nghĩ flags_ nên có cùng độ dài, nhưng có vẻ như không.

Tại sao?

+0

Không sử dụng các loại như 'uint32_t' cho một trường bit một chút ngớ ngẩn? (Nói chung, chúng chỉ nên được sử dụng khi bạn cần khớp chính xác với định dạng bên ngoài, và thậm chí sau đó, việc sử dụng chúng không rõ ràng.) –

Trả lời

6

Chuẩn (9,6 của the working draft) nói điều này:

quy định cụ thể một chút trường; chiều dài của nó được đặt ra từ tên trường bit bằng dấu hai chấm. Thuộc tính trường bit không phải là một phần của loại thành viên lớp . Biểu thức hằng số phải là một biểu thức không đổi không đổi với một giá trị lớn hơn hoặc bằng không. Biểu thức hằng số có thể lớn hơn số bit trong biểu diễn đối tượng ( 3.9) của loại trường bit; trong trường hợp này, các bit phụ được sử dụng như các bit đệm và không tham gia vào biểu diễn giá trị ( 3.9) của trường bit. Phân bổ các trường bit trong một đối tượng lớp được xác định thực hiện. Căn chỉnh các trường bit là được thực hiện theo định nghĩa. Các trường bit được đóng gói vào một số đơn vị phân bổ địa chỉ . [Lưu ý: các trường bit phân bổ các đơn vị phân bổ trên một số máy chứ không phải trên các máy khác. Các trường bit được gán từ phải sang trái trên một số máy, từ trái sang phải trên các máy khác. lưu ý end]

(tôi nhấn mạnh)

Vì vậy, nó sẽ phụ thuộc vào trình biên dịch của bạn. Điều gì dường như đang xảy ra trong trường hợp của bạn - và tôi sẽ mô tả hành vi khá bình thường - là nó chỉ kết hợp các bitfield cùng loại và sau đó đóng gói cấu trúc đến một ranh giới 4 byte, vì vậy trong trường hợp đầu tiên chúng ta có:

struct a { 
    uint32_t foreColor_ : 32; // 4 bytes (total) 
    uint32_t backColor_ : 32; // 8 bytes 
    uint16_t lfHeight_ : 16; // 10 bytes 
    uint16_t flags_: 4;  // 12 bytes 
    bool lfBold_: 1;   // 13 bytes 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; // still 13 bytes 
}; 

đó là sau đó đệm đến 16 byte, và trong lần thứ hai chúng ta có:

struct a { 
    uint32_t foreColor_ : 32; // 4 bytes (total) 
    uint32_t backColor_ : 32; // 8 bytes 
    uint16_t lfHeight_ : 16; // 10 bytes 
    uint8_t  flags_: 4;  // 11 bytes 
    bool lfBold_: 1;   // 12 bytes 
    bool lfItalic_: 1; 
    bool lfUnderLine_: 1; 
    bool lfDashLine_: 1; 
    bool lfStrike_: 1; 
    bool lfSubscript_: 1; 
    bool lfSuperscript_: 1; // still 12 bytes 
}; 

Mà không cần đệm và vẫn ở mức 12 byte.

+1

Nó được thực hiện xác định, không có nghi ngờ về nó, nhưng nó không nói nhiều về chất lượng thực hiện khi hai cấu trúc của ông có kích thước khác nhau. –

+0

* nhún vai * Tôi nghĩ rằng hầu hết các triển khai tôi đã làm việc với hành vi như thế. Chúng sẽ kết hợp như các trường nhưng không giống như các trường. Tôi thực sự nghĩ đó là cách nó được định nghĩa trong tiêu chuẩn cho đến khi tôi kiểm tra. –

+0

Tôi không nghĩ rằng tôi từng thấy một triển khai đã hoạt động theo cách này trước đây. G ++ chắc chắn không. –

0

Trình biên dịch cụ thể, trình biên dịch đang thực hiện các sắp xếp khác nhau để tối ưu hóa quyền truy cập vào các trường.

Nếu bạn muốn (cần) dựa trên căn chỉnh. (như xử lý tiêu đề mạng) Bạn cần sử dụng #pragma push, pop.

Hoặc __ thuộc tính __ (đóng gói) - là phần mở rộng GCC.

struct { 
... 
} __attribute__(packed) 

Điều này sẽ buộc trình biên dịch phải giải nén nó.

Các vấn đề liên quan