2010-12-28 47 views
11

Tôi đang viết một ứng dụng C++ cho Windows XP/Vista/7 bằng Visual Studio 2008. Một số cấu trúc của tôi sử dụng một trường bit, như trong ví dụ.Phần cuối của trường bit là bit quan trọng nhất?

typedef struct myStruct_tag 
{ 
    BYTE myVar1; 
    WORD myVar2; 
    WORD myVar3; 
    union 
    { 
     struct 
     { 
      BYTE   :1; 
      BYTE field1 :1; 
      BYTE field2 :1; 
      BYTE reserved :5; 
     } myBitField; 
     BYTE myVar4; 
    }; 
    BYTE myVar5; 
    BYTE myVar6; 
} myStruct_t; 

Phần cuối của trường là bit quan trọng nhất?

+2

Lưu ý: Theo tiêu chuẩn, MSB không được xác định. Trên nền tảng cụ thể của bạn, tôi nghi ngờ rằng 'reserved' chứa MSB nhưng tôi không tích cực. –

+0

@Billy: Điều đó trông giống như một câu trả lời cho tôi. –

+0

Er ... Đó là một câu hỏi khá lạ. Bạn chỉ có 3 bit trường trong khai báo của bạn. 2 trong số đó là các trường bit 1 bit, tức là không có vấn đề "kết thúc" nào với chúng, vì chỉ có 1 bit ở đó. Trường bit nhiều bit duy nhất được gọi là 'reserved', cho thấy nó không được sử dụng chút nào. Vì vậy, về cơ bản, trường bit duy nhất mà bạn đặt câu hỏi có thể áp dụng là 'reserved'. Bạn đang hỏi về 'reserved' đặc biệt? Nếu không, hãy làm rõ câu hỏi của bạn. – AnT

Trả lời

18

C99 chuẩn 6.7.2.1/10 (tôi nhấn mạnh):

An thực hiện có thể phân bổ bất kỳ đơn vị lưu trữ địa chỉ đủ lớn để tổ chức một bitfield. Nếu đủ không gian còn lại, một trường bit ngay sau một trường bit khác trong một cấu trúc sẽ được đóng gói thành các bit liền kề của cùng một đơn vị. Nếu không đủ không gian, dù một trường bit không vừa với được đặt vào đơn vị kế tiếp hay chồng chéo các đơn vị lân cận được xác định thực hiện. Thứ tự phân bổ các trường bit trong một đơn vị (thứ tự cao đến thứ tự thấp hoặc thứ tự thấp đến thứ tự cao) được xác định thực hiện. Căn chỉnh của đơn vị lưu trữ địa chỉ không xác định.

Vì vậy, thứ tự phải được ghi lại bằng cách triển khai trình biên dịch của bạn.

Tuy nhiên, rất nhiều về cách thực hiện bitfield được xác định hoặc không xác định rằng sử dụng chúng để tạo mô hình phần cứng, giao thức dây hoặc trường bit định dạng tệp theo kiểu di động không đáng để thử.

Nếu bạn muốn 'lĩnh vực chút' của bạn để mô hình một cái gì đó bên ngoài để chương trình của bạn (như những điều ở trên), sử dụng mặt nạ rõ ràng, thiết lập và thanh toán bù trừ các bit sử dụng các toán tử chuẩn bit-wise (|, '& , ~ , < < `, v.v ...). Sử dụng các hàm trợ giúp nội dòng (hoặc thậm chí các macro nếu bạn phải) để làm cho điều này dễ dàng hơn/rõ ràng hơn trong mã của bạn.

+2

+10 nếu có thể. Câu trả lời của bạn cho câu hỏi này là lý do tốt nhất để không sử dụng bitfields cho điều chính mà mọi người nghĩ rằng chúng hữu ích. –

+0

Tôi không nhận ra rằng mọi người cố gắng sử dụng chúng một cách hợp lý, cách sử dụng duy nhất tôi thấy là "nói chuyện với phần cứng từ chương trình của tôi sử dụng trình biên dịch X". Và nhìn vào tất cả các tỷ của "Tôi làm điều này trong trình biên dịch X, làm thế nào để làm điều đó trong trình biên dịch Y" câu hỏi. –

+0

@CodeAbominator: như một ví dụ, tôi đã nhìn thấy các trường bit được sử dụng để crack các thông điệp giao thức mạng hoặc các định dạng tệp nhị phân. Tôi cũng đã thấy một số mã đó không hoạt động khi được biên dịch cho một nền tảng khác. –

2

Nếu bạn đang hỏi về bit nào trong myBitField được lưu trữ trong đó bit của byte trong bộ nhớ, đó là rõ ràng không xác định bởi các tiêu chuẩn C. Bạn sẽ phải học bằng cách thử nghiệm. Có thể đáng giá, nếu bạn đang làm điều gì đó thực sự quan trọng, thay vào đó hãy sử dụng phương pháp mà bạn #define field1 làm giá trị hex (ví dụ: 0x40 hoặc 0x02) và đặt nó vào nơi bạn muốn.

+0

Thật không may, thử nghiệm chức năng của phần mã này ít nhất là vài tuần, nếu không phải là vài tháng. (Có rất nhiều thứ phải viết để thực sự kiểm tra bất kỳ điều gì vì tôi đang ở thời điểm mà mọi thứ còn lại để viết là phụ thuộc lẫn nhau vào mọi thứ khác.) Các hằng số được định nghĩa là một tùy chọn, nhưng tôi thích để sử dụng các trường bit vì trước đây sẽ yêu cầu lô * nhiều * hơn trong mã của tôi. –

+1

Vâng, một thử nghiệm nhanh sẽ cho bạn thấy những gì trình biên dịch đang làm ... chỉ cần xác định liên minh như trên, gán 0 cho 'myVar4', sau đó gán 1 cho' field1' và in giá trị kết quả từ 'myVar4'. Tôi muốn treo một tên trên bit không sử dụng mà bạn đã xác định trước khi 'field1', mặc dù, vì sợ rằng trình biên dịch tối ưu hóa nó đi. – jmaynard

4

Visual Studio 2008 tài liệu trình biên dịch chỉ:

Trật tự của dữ liệu khai báo là lĩnh vực bit là từ thấp đến cao chút

Từ "C++ Bit Fields", MSDN C++ Language Reference, Visual Studio 2008 version

+0

Như những người khác đã lưu ý, các tiêu chuẩn có liên quan không chỉ rõ điều này, và nó là tốt đẹp để viết mã tuân thủ tiêu chuẩn, nhưng đây là câu trả lời cho câu hỏi được hỏi, và người đọc có thể quyết định xem họ có muốn sử dụng quyền hạn của mình cho tốt hay không hoặc cho tuyệt vời. ; P – rakslice

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