2010-05-19 26 views

Trả lời

31

A union không phải là struct. Trong một union, tất cả dữ liệu chiếm cùng một không gian và có thể được coi là các loại khác nhau thông qua tên trường của nó. Khi bạn chỉ định true đến x.b, bạn sẽ ghi đè các bit đặt hàng thấp hơn của 20000.

Cụ thể hơn:

20000 trong hệ nhị phân: 100111000100000

19969 trong hệ nhị phân: 100111000000001

gì đã xảy ra ở đây là bạn đặt một giá trị một byte trong tổng số 1 (00000001) trong 8 thấp hơn -bit bit của 200000.

Nếu bạn sử dụng struct thay vì union, bạn sẽ có không gian cho cả intbool, thay vì chỉ cần int và bạn sẽ thấy kết quả mong đợi.

+4

+1: câu trả lời thực sự hay;) – Simon

3

Trong công đoàn, tất cả các thành viên dữ liệu bắt đầu ở cùng một vị trí bộ nhớ. Trong ví dụ của bạn, bạn chỉ có thể thực sự sử dụng một thành viên dữ liệu tại một thời điểm. Tính năng này có thể được sử dụng cho một số thủ thuật gọn gàng tuy nhiên, như phơi bày cùng một dữ liệu theo nhiều cách:

union Vector3 
{ 
    int v[3]; 
    struct 
    { 
    int x, y, z; 
    }; 
}; 

nào cho phép bạn truy cập vào ba số nguyên hoặc theo tên (x, y, z) hoặc như là một mảng (v).

+5

... hoặc có thể * anyway. Sau đó, một lần nữa, nó có thể chèn đệm giữa 'int' trong cấu trúc, trong trường hợp đó 'v [1]' và 'v [2]' sẽ KHÔNG tương ứng với 'y' và' z' như dự định. –

+0

Tôi không biết một trình biên dịch có thể đặt đệm giữa hai thành viên dữ liệu cùng loại. Padding xuất hiện khi các thành viên dữ liệu liên tiếp có kích thước khác nhau như một char theo sau bởi một đoạn ngắn (một char bổ sung sẽ được đóng gói giữa hai, rất có thể). Điều đó nói rằng, cấu trúc có thể được đệm sao cho tổng kích thước của nó được căn chỉnh từ, vì vậy nếu x, y và z là từng byte, có thể nó sẽ được đệm thành x, y, z, p hoặc p, x, y, z (mà thực sự sẽ phá vỡ ví dụ của tôi). –

+1

Lưu ý rằng cả C và C++ đều không có cấu trúc ẩn danh. Vì vậy, bạn cần đặt một tên như '} vs;' cho đối tượng struct. Hoặc dựa vào các phần mở rộng của trình biên dịch nếu bạn có thể. –

3

Chỉ một cửa hàng công đoàn một thành viên tại bất kỳ thời điểm đã định nào. Để có được kết quả xác định, bạn chỉ có thể đọc cùng một thành viên từ công đoàn được viết lần cuối đến công đoàn. Làm cách khác (như bạn đang ở đây) chính thức không đưa ra gì nhiều hơn hoặc ít hơn kết quả không xác định.

Đôi khi các công đoàn được cố tình sử dụng cho loại-punning (ví dụ: xem các byte tạo thành một phao). Trong trường hợp này, bạn có thể hiểu được những gì bạn nhận được. Loại ngôn ngữ cố gắng mang đến cho bạn cơ hội chiến đấu, nhưng nó thực sự không thể đảm bảo được nhiều.

+0

Tôi không nghĩ rằng bất cứ điều gì bạn đã nói ở đây là thực tế không chính xác nhưng tôi có vấn đề với việc sử dụng từ "undefined". "không xác định" là khi bạn đọc từ bộ nhớ chưa được khởi tạo; khi bạn có bốn byte và ghi đè lên một trong số họ, bạn nên biết chính xác những gì bạn sẽ có (nghĩ rằng nó có thể trông lạ khi bạn cast nó). – danben

+0

@danben, bạn thậm chí không biết bạn đang ghi đè lên một byte. Việc viết bởi boolean có thể ghi đè lên một phần ngẫu nhiên của int mà khi bạn đọc int mà không gán cho nó sau đó bạn có thể gây ra một ngoại lệ cpu hoặc tương tự (cả C và C++ cho phép những thứ như vậy). Hành vi thực sự không xác định, bất cứ điều gì cũng có thể xảy ra. –

+0

Tôi tin theo tiêu chuẩn rằng hành vi cụ thể này được xác định thực hiện. – danben

1

Liên minh trong C tạo điều kiện chia sẻ không gian bộ nhớ bằng các biến khác nhau.
Vì vậy, khi bạn thay đổi bất kỳ biến bên trong công đoàn, tất cả các giá trị của biến khác cũng bị ảnh hưởng.

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