接續上一篇教學文 結構—自訂不同資料型態綁在一起 ,讓我們繼續看看結構和指標、陣列的結合,會擦出什麼火花呢?
指向結構變數的指標
#include <stdio.h> struct student{ int age; char name[10]; }; int main(){ student lynn = {23, {'l', 'y', 'n', 'n', '\0'}}; student *one = &lynn; printf("%d \n", (*one).age); printf("%s \n", (*one).name); return 0; }
我們在主函數中宣告了一個結構變數 lynn,並對它進行初始化。
接下來,又宣告一個指標變數 one, student * one 的意思是:one 這個指標指向一個 student 類型的結構。
並且把 lynn 的地址取出來、賦值給變數 one。
接下來的程式:
printf("%d \n", (*one).age); printf("%s \n", (*one).name);
既然 one 是一個指標,而 *one 就是這個指標所指向的記憶體空間的內容,也就是一個結構。
在這個結構 *one 的後面使用 .age ,就是引用結構變數裡面的年紀。
同理,.name 就是結構變數裡面的陣列。
除了 .age 和 .name 這種寫法,我們也可以把它寫成這樣:
printf("%d", one -> age); printf("%d", one -> name);
也就是直接寫成「->」,表示 one 這個指標指向的結構變數的內容。
這和第一個寫法完全等價,不過又更加簡明,所以一般更常這樣寫。
把指向結構變數的指標,作為函數的參數
#include <stdio.h> #include <ctype.h> struct student{ int age; char name[10]; }; void new_one(student *one){ one -> age = 1000 + one -> age; for(int i = 0; one->name[i] != '\0'; i++) one -> name[i] = toupper(one -> name[i]); }; int main(){ student lynn = {23, {'l', 'y', 'n', 'n', '\0'}}; new_one(&lynn); printf("%d \n", lynn.age); printf("%s \n", lynn.name); return 0; }
在這主函數裡面,有宣告一個結構變數 lynn、並對其進行初始化。
接下來在主函數裡面呼叫一個函數 new_one,然後把 lynn 的地址當作參數傳給 new_one。
然後在 new_one 函數裡面,定義一個參數、來接傳過來的 lynn 指標。
當接到這個指標後,就利用參數 one,加上「->」,來修改指標 one 所指向的記憶體空間的內容。
在呼叫完 new_one 後,接著把變數 lynn 的內容印出來。
通過列印的結果,我們可以看出 new_one 這個函數,有沒有修改到主函數中的 lynn 變數。
修改到了!
實際上這個程式的過程是這樣:
當 main 函數呼叫 new_one 函數,並把 lynn 變數的地址、當作參數傳遞給 new_one 的時候,new_one 函數就拿到了這片記憶體空間的地址。
於是,我們就可以對這片記憶體空間裡面的內容進行修改。
也就相當於 new_one 函數伸出一隻手、到 main 函數裡面去修改 lynn 的值,所以 lynn 最後的值才會發生變化。
這和當我們把「指向一般變數的指標」當做函數的參數,傳遞給另外一個函數的時候,是完全一樣的情況。
結構陣列的特性
#include <stdio.h> struct girls{ int age; char name[10]; }; int main(){ girls TWICE[3] = {17, {'t', 'z', 'u', 'y', 'u', '\0'}, 19, {'m', 'i', 'n', 'a', '\0'}, 20, {'m', 'o', 'm', 'o', '\0'}, }; girls *ONCE = TWICE; for(int i = 0; i < 3; i++){ printf("%d \n", ONCE[i].age); printf("%s \n", ONCE[i].name); }; return 0; }
在這個程式中,利用建立好的結構 girls 來宣告一個陣列 TWICE。
在 TWICE 裡面有三個成員的資料,分別是 17 tzuyu、19 mina、20 momo。
接下來,宣告一個指標 ONCE,利用陣列的名字 TWICE 來對 ONCE 賦值。
為什麼能這麼做呢?
因為這就是一個普通的陣列呀! 陣列名稱,就相當於指向陣列第一個元素的指標,所以說這個賦值完全沒問題。
接下來,就利用 ONCE 這個指標,去印出它所指向的結構變數 age 和 name。
由於 ONCE 現在也是一個陣列,印出其內容的方式就是按照記憶體地址一個個印下去—— ONCE[0]、ONCE[1]、ONCE[2]。
總結來說,其實利用結構來宣告陣列,和用普通的變數來宣告的陣列,作法是一樣的。
陣列的名稱,仍相當於指向陣列第一個元素的指標。
—同場加映—
左到右分別是 Momo、Tzuyu 和 Mina 噢 <3 TWICE 大發(*゚∀゚*)