C語言中struct初始化
• 普通結構體的初始化
假設我們有如下的一段代碼,其中已有Student結構體,要求實例化一個Student對象並將其初始化。
#include <stdio.h> typedef struct _Student { unsigned age; unsigned grade; } Student; int main(int argc, char ** argv) { // 完成Student s的初始化,age = 16,grade = 1 printf("Age = %u\n", s.age); printf("Grade = %u\n", s.grade); return 1; }
▶ 實例化后為成員賦值方式
Student s; s.age = 16; s.grade = 1;
▶ 順序初始化方式
Student s = { 16, 1 };
▶ 點符號初始化方式
注意在此方式在,成員初始化可以不按照順序初始化,即可以亂序初始化。
Student s = { .grade = 1, .age = 16, };
▶ 冒號號初始化方式
注意在此方式在,成員初始化可以不按照順序初始化,即可以亂序初始化。
Student s = { grade : 1, age : 16, };
• 含有數組成員結構體的初始化
例如我們將Student結構體中加入char name[32]的字段,並初始化該字段。我們知道數組的初始化可以使用花括號進行所有元素或部分元素的初始化,譬如:
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int b[10] = { 0, 1, 2 };
那么含有數組成員的結構體初始化也可以使用這個規則。新的Student按照上述四種方式的初始化方式如下:
// 實例化后為成員賦值方式 Student s; s.age = 16; s.grade = 1; strcpy(s.name, "Jack");
// 順序初始化方式
Student s = { 16, 1, "Jack" };
Student s = { 16, 1, {'J', 'a', 'c', 'k', '\0'} };
// 點符號初始化方式
Student s = {
.name = "Jack",
.grade = 1,
.age = 16,
};
Student s = {
.name = {'J', 'a', 'c', 'k', '\0'},
.grade = 1,
.age = 16,
};
// 冒號號初始化方式
Student s = {
name : "Jack",
grade : 1,
age : 16,
};
Student s = {
name : {'J', 'a', 'c', 'k', '\0'},
grade : 1,
age : 16,
};
• 復雜結構體的初始化
復雜結構體無非是結構體中嵌套結構體,我們只需要結合上述規則就可以完成復雜結構體的初始化。例如我們將Student的結構體修改成這樣:
typedef struct _StudentInfo { unsigned age; char name[32]; } StudentInfo; typedef struct _Student { unsigned classes; unsigned grade; StudentInfo info; } Student;
那么綜合運用上述規則,初始化代碼可以寫成如下風格:
Student s = { .info = { name : "Jack", .age = 16 }, .grade = 1, classes : 2 };
C++語言中struct初始化
• 普通結構體的初始化
假設我們有如下的一段代碼,其中已有Student結構體,要求實例化一個Student對象並將其初始化。
#include <string> #include <iostream> using namespace std; typedef struct _Student { unsigned age; unsigned grade; string name; } Student; int main(int argc, char ** argv) { // 完成Student s的初始化,age = 16,grade = 1,name = “Jack” cout << "Age : " << s.age << endl; cout << "Grade : " << s.grade << endl; cout << "Name : " << s.name << endl; return 1; }
▶ 實例化后為成員賦值方式
Student s; s.age = 16; s.grade = 1; s.name = "Jack";
▶ 順序初始化方式
Student s = { 16, 1, "Jack" };
▶ 點符號初始化方式
注意在此方式在,和C風格不同,成員初始化不可以亂序初始化,否則編輯器將給出錯誤:“對不起,尚未實現:不平凡的代理初始值設定不受支持”。
Student s = { .age = 16, .grade = 1, .name = "Jack", };
▶ 冒號號初始化方式
注意在此方式在,和C風格不同,成員初始化不可以亂序初始化,否則編輯器將給出錯誤:“對不起,尚未實現:不平凡的代理初始值設定不受支持”。
Student s = { age : 16, grade : 1, name : "Jack", };
• 含有數組成員結構體的初始化
例如我們將Student結構體name字段的類型從string改為char [32],並初始化該字段。我們可以發現在C++中char數組嚴格視為數組,不能直接進行字符串賦值操作。如果我們將代碼寫成如下方式,編譯器將給出錯誤:“錯誤:C99 designator ‘name’ outside aggregate initializer”。
Student s = { age : 16, grade : 1, name : "Jack", };
正確的賦值方式就是嚴格按照數組初始化方式進行賦值:
Student s = { age : 16, grade : 1, name : {'J', 'a', 'c', 'k', '\0'}, };
需要說明一點的是,點符號和冒號的賦值方式可以混用,這個在上面C語言風格結構體初始化中可以看到運用,這一點在C++中也是適用的,譬如上面的代碼可以寫成:
Student s = { .age = 16, grade : 1, .name = {'J', 'a', 'c', 'k', '\0'}, };
• 復雜結構體的初始化
復雜結構體無非是結構體中嵌套結構體,我們只需要結合上述規則就可以完成復雜結構體的初始化。例如我們將Student的結構體修改成這樣:
typedef struct _StudentInfo { unsigned age; char name[32]; } StudentInfo; typedef struct _Student { unsigned classes; unsigned grade; StudentInfo info; } Student;
那么綜合運用上述規則,初始化代碼可以寫成如下風格:
Student s = { .classes = 2, grade : 1, .info = { age : 16, .name = { 'J', 'a', 'c', 'k' } } };
一些使用建議
• 無論采用哪種方式初始化結構體,請按照成員出現的順序進行初始化。
• 初始化方式盡量采用同種風格,即點符號風格和冒號風格不要混用。
• 點符號方式是C99標准,冒號方式是GCC的擴展,強烈建議使用點符號方式。
• 字符數組初始化請嚴格按照數組初始化規則進行初始化。
Aggregate Initialization
http://en.cppreference.com/w/cpp/language/aggregate_initialization
https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html