2013-11-04 26 views
0

我想初始化這個結構:如何在C中的聯合中使用指針?

typedef struct 
{ 
    int num; 
    union 
    { 
     const char** ppStrList; 
     const char* pStr; 
    }; 
    union 
    { 
     int num1; 
     int num2; 
    }; 
} tMyStruct; 

如果我嘗試當我宣佈變量,我得到一個錯誤初始化這個結構:例如,

const char *gpStr = "str"; 

const char *gpStrList[2] = 
{ 
    {"str1"}, 
    {"str2"} 
}; 

tMyStruct myStruct[2] = 
{ 
    {0,{gpStrList},{3}}, 
    {1,{gpStr},{4}} 
}; 

變量gpStr不容被用來初始化結構

但它可以在函數中沒有問題初始化:

int main(int argc, char *argv[]) 
{ 
    myStruct[0].num = 0; 
    myStruct[0].ppStrList = gpStrList; 
    myStruct[0].num1 = 3; 

    myStruct[1].num = 0; 
    myStruct[1].pStr = gpStr; 
    myStruct[1].num2 = 3; 
} 

爲什麼結構不能初始化何時宣佈?

我認爲工會有一個特殊的行爲,因爲如果我不使用聯合問題不存在。例如:

typedef struct 
{ 
    int num; 
    union /* Union to contain ppStrList and pStr pointers */ 
    { 
     const char** ppStrList; 
     const char* pStr; 
    }; 
    union 
    { 
     int num1; 
     int num2; 
    }; 
} tMyStruct1; 


typedef struct 
{ 
    int num; 
    /* I don´t use an union */ 
    const char** ppStrList; 
    const char* pStr; 

    union 
    { 
     int num1; 
     int num2; 
    }; 
} tMyStruct2; 

const char gStr[] = "str"; 

const char *gpStrList[2] = 
{ 
    {"str1"}, 
    {"str2"} 
}; 

tMyStruct1 myStruct1[2] = /* Structure with union inside */ 
{ 

    {0,{gpStrList},{3}}, 
    {1,{gStr},{4}} /* <--- Error here if I use gStr address with union */ 
}; 

tMyStruct2 myStruct2[2] = /* Structure without union inside */ 
{ 
    {0,gpStrList,NULL,{3}}, 
    {1,NULL,gStr,{4}} /* <--- No poblem here if I use gStr address */ 
}; 
+0

我敢說,這: '工會 { INT NUM1; int num2; };' 證明你根本不應該使用聯合。 – Dariusz

回答

3

在文件範圍(不論是否爲static)初始化的變量以及在塊範圍內使用static持續時間初始化的變量只能用常量初始化。自動變量(必須在塊範圍內)可以用表達式初始化。

此外,當聯合初始化時,除非使用指定的初始化程序,否則初始化程序必須匹配第一個成員。隨着C99或更高版本,你可以寫:

typedef struct 
{ 
    int num; 
    union 
    { 
     const char** ppStrList; 
     const char* pStr; 
    }; 
    union 
    { 
     int num1; 
     int num2; 
    }; 
} tMyStruct; 

const char gpStr[] = "str"; 

const char *gpStrList[2] = 
{ 
    "str1", 
    "str2" 
}; 

tMyStruct myStruct[2] = 
{ 
    { .num = 0, { .ppStrList = gpStrList }, { .num1 = 3 } }, 
    { .num = 1, { .pStr  = gpStr  }, { .num2 = 4 } }, 
}; 

注意微調的類型gpStr。您不必爲所有元素使用指定的初始值設定項,但一致性表明您可能應該這樣做。另請注意,兩個名稱不同的成員int的聯合會略微毫無意義。聯盟的不同元素通常應該是不同的類型。

+0

遠比我的微薄貢獻更清晰更完整!獲得我的投票! – Floris

+0

我必須使用指定的初始化工具來初始化'union'。關於兩個不同名稱的「int」成員的「union」。我同意,只是爲了澄清,代碼代表了一個真正的問題,但此代碼僅用於教學目的。 – leiva

+0

@leiva:夠公平的,並不是很令人驚訝。這只是一個小問題。如果您需要再次詢問,請確保在外部聯合中使用兩種不同的類型(可能是int和char *),或者將第二個聯合離開示例。 –

0

不科學的答案:

我想你只能用常數初始化。在第一種情況下,您正在初始化(即在程序運行之前分配一個值)和一個變量;根據定義,變量在程序運行之前沒有「可訪問」的值。在你的第二個例子中,「初始化」實際上是一個帶有變量的「賦值」,沒關係。我認爲這與你有一個工會無關。

最簡單的例子:

#include <stdio.h> 
int one = 1; 
int two = one; 
int main(void) { 
    printf("one is %d; two is %d\n", one, two); 
} 

當我嘗試編譯,我得到

consts.c:3: error: initializer element is not constant 

我希望這個澄清的事情。

+1

好奇的是,標籤爲「C」的下一個問題的標題是「警告:初始化元素不是常量」......顯然有流行病! – Floris

0

問題是隻能初始化聯合的第一個元素,除非使用明確的指示符。所以下面的工作:

tMyStruct myStruct[2] = 
{ 
    {0,{gpStrList},{3}}, 
    {1,{.pStr = "str"},{4}} 
};