2013-05-18 32 views
16

giả sử chúng ta có một công đoàn:Làm thế nào để kiểm tra loại hiện đang được sử dụng trong công đoàn?

typedef union someunion { 
    int a; 
    double b; 
} myunion; 

Có thể kiểm tra những gì loại là trong sự hiệp nhất sau khi tôi đặt ví dụ a = 123? Cách tiếp cận của tôi là thêm công đoàn này vào một số cấu trúc và đặt uniontype thành 1 khi đó là int và 2 khi nó tăng gấp đôi.

typedef struct somestruct { 
    int uniontype 
    myunion numbers; 
} mystruct; 

Có giải pháp nào tốt hơn không?

Trả lời

13

Có giải pháp nào tốt hơn không?

Không, giải pháp mà bạn hiển thị là giải pháp tốt nhất (và duy nhất). union s khá đơn giản, không "theo dõi" những gì bạn đã gán cho cái gì. Tất cả những gì họ làm là cho phép bạn sử dụng lại cùng một phạm vi bộ nhớ cho tất cả các thành viên của họ. Họ không cung cấp bất cứ điều gì khác ngoài đó, do đó, kèm theo chúng trong một struct và sử dụng một "loại" lĩnh vực để theo dõi chính xác là điều đúng để làm.

+7

FYI, kỹ thuật này được gọi là "công đoàn được gắn thẻ". –

+2

Một giải pháp tốt hơn là sử dụng các giá trị enum thay vì 1, 2, v.v. –

6

C không tự động theo dõi trường nào trong liên minh hiện đang được sử dụng. (Trên thực tế, tôi tin rằng đọc từ kết quả trường "sai" trong hành vi được xác định thực hiện.) Như vậy, tùy thuộc vào mã của bạn để theo dõi mã nào hiện đang được sử dụng/điền vào.

Cách tiếp cận của bạn để giữ biến 'uniontype' riêng biệt là một cách tiếp cận rất phổ biến cho điều này và sẽ hoạt động tốt.

3

Không có cách nào để truy vấn trực tiếp loại hiện được lưu trữ trong union.

Cách duy nhất để biết loại được lưu trữ trong union là có cờ rõ ràng (như trong ví dụ mystruct) hoặc để đảm bảo điều khiển chỉ chuyển đến các phần nhất định của mã khi công đoàn có phần tử hoạt động đã biết .

2

Tùy thuộc vào ứng dụng, nếu đó là đối tượng sống ngắn, bạn có thể mã hóa loại trong luồng điều khiển, ví dụ: có khối riêng biệt/chức năng cho cả hai trường hợp

struct value { 
     const char *name; 
     myunion u; 
    }; 

    void throwBall(Ball* ball) 
    { 
    ... 
    struct value v; 
    v.name = "Ball"; v.u.b = 1.2; 
    process_value_double(&v);  //double 
    struct value v2; 
    v2.name = "Age"; 
    v2.u.a = 19; 
    check_if_can_drive(&v2);  //int 
    ... 
    } 

    void countOranges() 
    { 
     struct value v; 
     v.name = "counter"; 
     v.u.a = ORANGE; 
     count_objects(&v);   //int 
    } 
2

Cảnh báo: sau đây là chỉ cho mục đích học tập:

Bạn có thể sử dụng một số thủ thuật xấu xí để làm như vậy (miễn là các kiểu dữ liệu trong sự hiệp nhất của bạn có các kích thước khác nhau, đó là trường hợp hiện tại):

#include <stdio.h> 

typedef union someunion { 
    int a; 
    double b; 
} myunion; 

typedef struct somestruct { 
    int uniontype; 
    myunion numbers; 
} mystruct; 


#define UPDATE_CONTENT(container, value) if (\ 
              ((sizeof(value) == sizeof(double)) \ 
               ? (container.uniontype = ((container.numbers.b = value), 2)) \ 
               : (container.uniontype = ((container.numbers.a = value), 1)))) 

int main() 
{ 
    mystruct my_container; 

    UPDATE_CONTENT(my_container, 42); 
    printf("%d\n", my_container.uniontype); 
    UPDATE_CONTENT(my_container, 37.1); 
    printf("%d\n", my_container.uniontype); 
    return (0); 
} 

Nhưng tôi khuyên bạn không nên làm điều này.

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