2014-09-19 57 views
0

我試圖瞭解以下內容:使用'union'和'enum'的好例子?

'聯盟'的行爲就像一個變量,我可以存儲不同類型的值。 如果在'float'類型的存儲值中,但是我將其讀作'short'會怎麼樣?

有沒有什麼方法可以確定我將從工會中檢索的價值類型?

我該如何處理這種情況?

我在某處看到一個音符,他談到了使用'enum'這樣的例子,但是沒有足夠好的解釋爲什麼?

您能否解釋爲什麼使用'union'和'enums'有用/安全?或者顯示一些例子。

在此先感謝,尼克。

+0

即使沒有成員在邊聯合中,對於只有一個成員,聯合會分配基於哪個成員大小較大的內存。使用此內存可以訪問該聯合中的任何成員。因爲它基於member.and分配高內存在同一時間,只有一個可以訪問的地方是可能的。所以沒有問題。 「 – 2014-09-19 05:26:07

+0

」如果在'float'類型的存儲值中,但是我將它讀作'short'?「 - 未定義的行爲。 「有什麼方法可以確定我將從工會中取回哪些類型的價值?」 - 電腦有記憶;用它來表示聯合中的什麼類型的值。枚舉是表示存儲哪種類型的一種方法。 – 2014-09-19 05:52:00

回答

3

我相信這是一種執行​​3210或總和類型的方法。 例如在C99使用anonymous union

enum kind_en { knothing, kint, kfloat, kstring }; 
struct value_st { 
    enum kind_en kind; 
    union { 
    int n;  // when kint 
    float f; // when kfloat 
    char* s; // when kstring 
    }; 
}; 

然後例如

void print_value (struct value_st* v) { 
    if (!v) {puts("nil"); return; }; 
    switch (v->kind) { 
    case knothing: puts("nothing"); return; 
    case kint: printf("int#%d", v->n); return; 
    case kfloat: printf("float#%g", v->f); return; 
    case kstring: printf("string'%s'", v->s); return; 
    default: abort(); 
    } 
} 

struct value_st* make_int_value(int i) { 
    struct value_st* val = malloc(sizeof(struct value_st)); 
    if (!val) { perror("malloc int value"); exit(EXIT_FAILURE); }; 
    val->kind = kint; 
    val->n = i; 
    return val; 
} 

從上個世紀更古老的例子是XEventXlib

注意的一些編程語言都有補助數額類型的更簡單的方法。 OCaml中你只需要

type val_t = 
    Knothing | Kint of int | Kfloat of float | Kstring of string;; 

,最重要的是你有pattern matching

1

問題的答案:

  1. 是,編碼類型到包含聯合的結構:

    union { 
        float f; 
        int i; 
    } my_union; 
    
    enum { 
        its_a_float, 
        its_an_int 
    } flavor; 
    
    struct { 
        flavor x; 
        my_union u; 
    } data_blob; 
    
  2. 不確定我饒有興趣地回答你的問題,是什麼情況?

  3. 見上

  4. 這是非常有用的,當你不知道在編譯時,你有確切的數據/需求和需要處理相同的邏輯數據的多種口味。

1

添加新的申請ENUM類型,並保持約電流型

#include <stdio.h> 
#include <conio.h> 
#include <stdlib.h> 

typedef enum types_tag { 
    CHAR, 
    INT, 
    FLOAT 
} types_t; 

typedef union value_tag { 
    char c; 
    int i; 
    float f; 
} value_t; 

typedef struct store_tag { 
    types_t type; 
    value_t value; 
} store_t; 

void printValue(const store_t *o) { 
    switch (o->type) { 
    case CHAR: 
     printf("%c\n", o->value.c); 
     break; 
    case INT: 
     printf("%d\n", o->value.i); 
     break; 
    case FLOAT: 
     printf("%.3f", o->value.f); 
     break; 
    default: 
     exit(EXIT_FAILURE); 
    } 
    return; 
} 

void main() { 
    store_t a; 

    a.type = CHAR; 
    a.value.c = 'A'; 
    printValue(&a); 
    a.type = FLOAT; 
    a.value.f = 10.45; 
    printValue(&a); 

    _getch(); 
} 

除了有信息,你可以保持剛剛在一堆內存信息,並用void *

#include <stdio.h> 
#include <conio.h> 
#include <stdlib.h> 

typedef enum types_tag { 
    CHAR, 
    INT, 
    FLOAT 
} types_t; 

typedef struct store_tag { 
    types_t type; 
    void* value; 
} store_t; 

void printValue(const store_t *o) { 
    switch (o->type) { 
    case CHAR: 
     printf("%c\n", *(char*)(o->value)); 
     break; 
    case INT: 
     printf("%d\n", *(int*)(o->value)); 
     break; 
    case FLOAT: 
     printf("%.3f", *(float*)(o->value)); 
     break; 
    default: 
     exit(EXIT_FAILURE); 
    } 
    return; 
} 

void main() { 
    store_t a; 

    a.type = CHAR; 
    a.value = malloc(1); 
    *((char*) a.value) = 'A'; 
    printValue(&a); 
    free(a.value); 

    a.type = FLOAT; 
    a.value = malloc(sizeof(float)); 
    *((float*) a.value) = 34.7; 
    printValue(&a); 
    free(a.value); 

    _getch(); 
} 

並添加一些功能來隱藏創建和刪除變量。

+0

是不是完全像我的答案(除非不使用匿名聯合,在這種情況下很方便)? – 2014-09-19 05:35:36

+0

也許,剛剛寫了很長時間,發佈後看到它。 – 2014-09-19 05:37:07

+0

一直髮生在我身上......一點,'main'是'int'類型並返回一個值。僅僅因爲你的編譯器會讓你擺脫「空白」 - 不要。 :) – 2014-09-19 05:42:37