C 語言:結構變數與指標

接續上一篇教學文 結構—自訂不同資料型態綁在一起 ,讓我們繼續看看結構和指標、陣列的結合,會擦出什麼火花呢?

 

指向結構變數的指標

#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 大發(*゚∀゚*)