結構變量 structure variable
C中struct是用來將多種數據類型組合到一起包裝成一種新的類型。創建一個struct
數據類型需要:
- 建立結構的格式或佈局
- 聲明遵循該佈局的變量
- 獲取對一個結構變量的各個成員(member)或者字段(field)的訪問
建立結構聲明
struct book {
char title[30];
char author[30];
int price;
};
這樣的聲明是解釋了一個標記(可以理解爲別名)爲book
的struct
類型所包含的數據類型:一個字符串數組-書名,一個字符串數組-作者,一個int-價格,就像一個模板一樣。這樣的聲明只是聲明瞭這樣的一個數據對象,並沒有實際非配存儲空間。當使用這個數據類型時,纔會分配空間:
struct book my_book;
這裏就定義了一個book
類型的struct
對象,需要注意的是它裏面的數據是沒有進行默認初始化的。
定義結構聲明
struct book my_book;
這個語句會使得編譯器分配空間來容納兩個數組一個int。還可以這樣定義:
struct
初始化類似於數組的初始化:
struct book mybook = {
"愛你就像愛生命",
"王小波",
29;
};
還可以指定初始化項目:
struct book book1 = {
.author = "王小波",
.title = "愛你就像愛生命",
.price = 29
};
這樣初始化不需要保持順序,而且可以只初始化若干個字段。類似於數組的指定元素初始化,會出現值的覆蓋情況:
struct book book1 = {
.price = 29,
.author = "王小波",
35
};
此時書的價格變爲35。
struct
結構的元素訪問可以用點運算符:
struct book {
char title[30];
char author[30];
int price;
};
int main() {
struct book mybook = {
"愛你就像愛生命",
"王小波",
29.
};
printf("%s",mybook.title);
return 0;
}
結構數組
聲明結構數組:
struct book books[20]
聲明瞭一個可以容納20本書的數組books
。
嵌套結構
允許一個結構的組成元素裏面包含另一種結構。
struct publishing_house {
char name[30];
char location[30];
};
struct book {
struct publishing_house publishingHouse;//book這個類型包含出版社信息結構
char title[30];
char author[30];
int price;
};
int main() {
struct book mybook = {
{"上海文藝出版社",
"上海"},
"愛你就像愛生命",
"王小波",
29
};
return 0;
}
結構指針
聲明一個指向結構的指針與普通指針聲明方式差不多:
struct book * ptobook;
但是和數組不同之處在於結構的名字並不是該結構的地址,對ptobook
進行賦值時應該使用&
運算符進行取地址操作:
ptobook = & my_book;
使用指針訪問結構成員
兩種方法:
->
運算符
ptobook->author
返回的是ptobook
指向的book結構的author
字段值,是個字符串數組。*
運算符與.
運算符結合
(*ptobook).author
也是如此。
結構用於傳參
結構用於傳參可以有三種方式:
- 傳遞結構成員給函數
- 傳遞結構指針給函數
- 傳遞結構本身給函數
需要注意的是不同於傳遞結構指針的方式中函數會操作原有結構,向函數傳遞結構本身會產生一個原有結構的拷貝,這個拷貝是一個自動變量。
不同於數組無法互相賦值:
struct book mybook = {
{"上海文藝出版社",
"上海"},
"愛你就像愛生命",
"Bob",
29
};
// int array1[2] = {1,2};
// int array2[2];
// array2 = array1;//報錯:Array type 'int [2]' is not assignable array2是常量,=左邊應該是變量。數組無法整體賦值。
struct book the_same_book;
the_same_book = mybook;//合法
mybook.price = 10;
mybook.author[0] = 'A';
printf("my_book: %s\n",mybook.author);
printf("the same book: %s\n",the_same_book.author);
發現這樣操作my_book
裏面的所有成員都被重新拷貝了另一份,即使是數組也被完整拷貝了。
結構也可以作爲函數的返回值。
在結構中使用指針的危害
struct name {
char firs[20];
char last[20];
};
struct pname {
char *first;
char *second;
};
在上面的代碼中,兩個struct結構中用了數組和指針兩種方式來表明兩個字符串變量。但是在指針方式中,指針沒有初始化,那麼創建的pname
對象中的字符串存儲位置也就不確定,很可能會造成程序的崩潰。而使用數組方式就不用擔心,因爲數組會被分配專門的空間,不會造成修改其他正在被佔用的內存裏的數據。
聯合(Union)數據結構
union
這種數據結構很有意思,它允許你像聲明struct
那樣創建一個模板,裏面可以有各種數據類型。但是不同的是,它在某個時刻只能存儲一個模板裏的數據類型,也就是說,union
是用來存放不確定數據類型的數據。
union union_ {
int money;
double price;
char name;
};
這樣的一個union_
某個時刻只能存儲int
、double
、char
三種類型其中的一個數據。使用示例:
union union_ foo;
foo.money = 1000;//將1000存儲在foo中
foo.name = 'A';//清除1000,將'A'存儲在foo中
foo.price = 100.5;//清除'A',將100.5存儲在foo中
編譯器給foo
分配的空間按int
、double
、char
三種數據類型中所需的最大字節數來分配以保證可以滿足可能出現的三種存儲情況。union
同樣支持互相賦值及->
運算符。union
可以聲明struct
是它可能需要存儲的數據類型。