認識C中的結構體

  C中結構體是另一種表示數據形式的方式,結構體中能夠表示C中的基本數據形式,如int,double....結構體可讓咱們更好的表示數據。下面來看看結構體。數組

  說到結構體首先要了解的是它的申明形式,要申明一個結構體形式以下:函數

 1 #include<stdio.h>
 2 #define LEN 20
 3 
 4 //申明一個結構體
 5 struct name {
 6     char firstname[LEN];
 7     char lastname[LEN];
 8 };
 9 
10 //申明一個結構體
11 struct guy {
12     struct name handle;        //結構體嵌套
13     char favfood[LEN];
14     char job[LEN];
15     int age;
16 };
17 
18 int main(int argc, char* argv[])
19 {
20   ........
21 }

  在結構體中能夠有基本的數據類型例如上面的int,char數組,也能夠嵌套有其餘結構體,例如上面結構體guy中就存在另一個結構體name。值得注意的是,咱們在申明一個結構體的時候,計算機並無爲數據分配空間,而是在咱們建立結構變量的時候纔會進行分配。建立結構變量的形式以下:ui

 1 struct guy new_guy; spa

  在計算機執行到上面這句時,計算機會爲變量分配內存。如上guy中包含一個name結構體,name結構體中是由兩個20個char所佔字節組成,共計2*20=40字節,而favfood和job也是兩個長度爲20的char數組,age是一個int類型,因此一個guy類型的變量所佔字節數共計爲40+20+20+4=84。指針

  如今咱們知道如何申明一個結構體和定義一個結構體變量了。先看看下面的代碼:code

 1 struct guy new_guy1 = { //結構體的初始化
 2         {"zhou","xuanyu"},
 3         "tomato",
 4         "student",
 5          22
 6     };
 7 struct guy new_guy2 = { //結構體的初始化
 8         .handle = {"zhou","xuanyu"},
 9         .job = "student",
10     };

  上面一段代碼是對一個結構體進行初始化,對於new_guy1,咱們對它的每個屬性都初始化了,而對於new_guy2咱們僅僅初始化了他的handle和job。對於一個結構體咱們應該怎麼訪問結構體中的每個項呢?不錯,是使用 . 運算符。例如:對象

 1 printf("%s",new_guy2.handle); ,就能夠打印出"zhouxuanyu"。再看看下面這段代碼(其中的結構體guy在上面已定義):blog

 1 int main(int argc, char* argv[])
 2 {
 3     struct guy new_guy[2] = {    //定義一個結構體數組
 4         {
 5             {"zhou","xuanyu"},"tomato","student",22    //初始化數組第一項
 6         },
 7         {
 8             {"hu","jiannan"},"fruit","student",22    //初始化數組第二項
 9         }
10     };
11     
12     struct guy * him; //指向結構體guy的指針
13     him = &new_guy[0]; //將指針指向guy數組
14     
15     printf("address #1:%p, #2:%p\n",&new_guy[0],&new_guy[1]);
16     printf("pointer #1:%p, #2:%p\n",him,him+1);
17     
18     printf("him->handle.firstname is %s,(*him).age is %d\n",him->handle.firstname,(*him).age);
19     him++;
20     printf("him->job is %s,(*him).handle.lastname is %s\n",him->job,(*him).handle.lastname);
21 }

  在上面這段代碼中,咱們定義了一個guy類型的數組,定義一個結構體數組的形式和定義通常數組同樣。在上面代碼第12行中咱們申明瞭一個指向結構體的指針him,利用指針咱們能夠對數據的操做會更加靈活。在13行,咱們初始化了這個指針,這裏要注意的是結構體的名稱和數組名不一樣,數組名就是數組其實元素的地址,因此能夠這樣作int *p = a,假設a是一個int類型的數組,可是結構體不行,必須使用&取地址。所用上面15,16行打印出來的地址是同樣的。上面的代碼中又出現了一個新的運算符->。它的做用和剛剛說的 . 運算符同樣,只是做用的對象不同,簡單的記法就是:指針使用->訪問結構體中的項,而結構體變量使用.訪問它的項。到如今咱們已經大概瞭解告終構體的基本用法。下面來看看結構體在函數中使用的幾種方式:內存

 1 #include<stdio.h>
 2 #define LEN 20
 3 
 4 struct Book {                 //定義結構體
 5     char bookname[LEN];
 6     double price;
 7     char author[LEN];
 8 };
 9 
10 //三個函數都用於改變書的價格
11 double changebook1(double);        //由於只改變書的價格,直接將價格做爲參數傳入函數
12 double changebook2(struct Book *);    //傳入一個指向Book類型的指針
13 double changebook3(struct Book);    //傳入一個結構體
14 
15 
16 int main(int argc, char* argv[])
17 {
18     struct Book book = {
19         "C Primer Plus",75.0,"John"
20     };
21     
22     struct Book * p_book = &book;
23     
24     printf("book's price is: %f\n",book.price);
25     printf("after changebook1(),return value is: %.2f, book's price is: %.2f\n",changebook1(book.price),book.price);
26     double new_price2 = changebook2(p_book);
27     printf("after changebook2(),return value is: %.2f, book's price is: %.2f\n",new_price2,book.price);
28     double new_price3 = changebook3(book);
29     printf("after changebook3(),return value is: %.2f, book's price is: %.2f\n",new_price3,book.price);
30 }
31 
32 double changebook1(double price){
33     return price * 2;
34 }
35 
36 double changebook2(struct Book * book){
37     book->price *= 2;
38     return book->price;
39 }
40 
41 double changebook3(struct Book book){
42     book.price *= 4;
43     return book.price;
44 }

  上面的代碼中,咱們定義了三個函數用來改變book的價格,第一個是直接將double類型的pirce傳入,第二個是將一個指向結構體的指針傳入,第三個是將整個結構體傳入。最後打印出函數運行以後的結構,以下:it

  

 

 

 

 

  從結果能夠看出,只有changebook2()函數才真正的將書的價格改變了。這是爲何呢?緣由是這樣的,方法二是將一個指針做爲參數傳入函數,指針指向的是原始數據,因此咱們所作的全部操做都是在原始數據上進行的。而方法三傳入的是一個結構體,在調用函數changebook3()的時候,會根據模板Book建立一個自動變量,而後這個變量的成員會被初始化與原始數據同樣副本。而咱們所進行的操做都是在這個副本上進行的,因此不會對原始數據有任何改變。可是這樣的作法會對內存有很大的浪費,因此咱們通常使用的第二種方式,可是第二種方式會有破壞數據的可能,該怎麼辦呢?在C中const關鍵字能夠解決這個問題。若是咱們對原始數據不須要進行修改,這時候能夠將傳入函數的指針用const修飾。

相關文章
相關標籤/搜索