2014-10-10 57 views
7

我正在優化一個項目。它包含一個用戶可以一次選擇一個選項的選項結構。除了該選項外,我們還使用標誌變量來檢查爲此記錄設置了哪個選項值。 爲了使內存高效,我想將結構轉換爲聯合。但是,我怎麼知道哪個變量值是聯合設置的。因爲聯合沒有限制獲取變量的值,甚至沒有設置。如何知道爲聯合設置了哪個變量值?

struct options{ 
    int basicPay; 
    int lumsumPay; 
    int mothlyPay; 
    int weeklyPay; 
    int dailyPay; 
    int anualPay; 

    int payType; // Flag variable to check which option is selected 
}; 

union OptimizeOptions{ 
    int basicPay; 
    int lumsumPay; 
    int mothlyPay; 
    int weeklyPay; 
    int dailyPay; 
    int anualPay; 

    int payType; // Confuse at here 
}; 
+0

@ user3121023是對的 - 只有當一個或多個成員具有不同類型時,才需要聯合。還有拼寫:'lumpsumPay','monthlyPay'和'annualPay'。 – 2014-10-10 17:37:12

回答

14

您是否在內嘗試過union?讓我們來看看下面的例子等價:

union options{ 
    int basicPay; 
    int lumsumPay; 
    int mothlyPay; 
    int weeklyPay; 
    int dailyPay; 
    int anualPay; 
}; 

struct record{ 
    union options op; // Options union 
    int payType; // Flag variable to check which option is selected 
} 

工會(options)將保留存儲器,用於其最大的變量,你可以設置它的價值和你的結構(記錄)將跟蹤該聯盟的內存塊和payType標誌值可以設置,這會告訴你的程序獲取工會的相關變量。

+12

'聯合選項* op'不需要是一個指針,並且如果它是'union options op',會更容易使用'struct record'。 – cpburnz 2014-10-10 14:08:22

+0

是的你是對的。 – Ali 2014-10-10 18:49:41

16

工會患有一個問題,即沒有簡單的方法可以知道工會的哪個成員最後一次發生了變化。爲了跟蹤此信息,您可以將union嵌入具有另一個成員(稱爲「標記字段」或「判別式」)的結構中。標記字段的用途是提醒哪個成員被更改/更新。你可以試試這個:

typedef struct{ 
     int payType;  // Tag field 

     union{ 
      int basicPay; 
      int lumsumPay; 
      int mothlyPay; 
      int weeklyPay; 
      int dailyPay; 
      int anualPay; 
     }OptimizeOptions; 

}Options; 

但是,有沒有必要寫工會六個獨立成員的情況下,都是int類型。因此,它可以減少到

typedef struct{ 
    enum{BASIC_PAY, LUMSUM_PAY, MONTHLU_PAY, WEEKLY_PAY, DAILY_PAY, ANNUAL_PAY} payType; 
    int pay; 
}Options; 

允許瞭解使用標記字段的一個簡單的例子。假設我們需要一個可以存儲intdouble類型數據的數組。這可以通過使用union來實現。因此,首先定義一個聯合類型,它將存儲intdouble

typedef union { 
     int i; 
     double d; 
} Num; 

接下來我們要創建一個數組,其元素爲Num

Num num_arr[100]; 

現在,假設我們要分配的num_arr的元素0存儲25,而元素13.147。這可以作爲

num_arr[0].i = 25; 
num_arr[1].d = 3.147; 

現在假設我們在寫這將打印num_arr元素的函數來完成。功能如下:

void print_num(Num n) 
{ 
    if(n contains integer) 
     printf("%d", n.i); 
    else 
     printf("%f", n.d); 
} 

等等! print_num如何決定n是否包含整數或double

這將通過使用標記字段來完成:

typedef struct{ 
    enum{INT, DOUBLE} kind;  //Tag field 
    union{ 
     int i; 
     double d; 
    }u; 
}Num; 

因此,每個值被分配給的u成員時間,kind被設置爲INTDOUBLE提醒我們實際存儲了什麼類型。例如:

n.u.i = 100; 
n.kind = INT; 

print_num功能會是這樣的:

void print_num(Num n) 
{ 
    if(n.kind == INT) 
     printf("%d", n.i); 
    else 
     printf("%f", n.d); 
} 

:這是程序員的責任,每個分配的union成員更新標記字段。忘記這麼做會導致錯誤,正如comment by @ j_random_hacker所指出的那樣。

+1

您忘記聲明類型爲'union OptimizeOptions'的類型_--目前您只是聲明瞭聯合類型本身,但沒有聲明該類型的字段。 – 2014-10-10 16:46:53

+0

@亨寧馬克霍姆;接得好 :)。現在它是固定的。 – haccks 2014-10-10 16:50:51

+1

我建議將「kind」中的「can」改爲「must」將被設置爲「INT」或「DOUBLE」,以明確這是程序員必須自己做的事情;忘記做會造成錯誤。 – 2014-10-10 17:24:35

相關問題