結構體將異質資料封裝為單一型別,陣列提供批量管理,指標實現動態存取與函式傳遞。三者結合是 C 語言資料處理的核心模式。本文系統講解結構體陣列初始化、結構體指標存取語法(. vs ->)、指標陣列與指向陣列的指標區別,並附贈通訊錄、成績統計兩大實戰範例。
struct Student {
int num;
char *name; // 指向字串常數區
char sex;
float score;
};
struct Student class[5] = {
{101, "Li ping", 'M', 45.0},
{102, "Zhang ping",'M', 62.5},
{103, "He fang", 'F', 92.5},
{104, "Cheng ling",'F', 87.0},
{105, "Wang ming", 'M', 58.0}
}; // 未指定長度時編譯器自動推導為 5
int main() {
int i, fail = 0;
float sum = 0;
for (i = 0; i < 5; ++i) {
sum += class[i].score;
if (class[i].score < 60) ++fail;
}
printf("總分: %.1f 平均: %.1f 不及格: %d\n", sum, sum/5, fail);
return 0;
}
struct Student stu = {102, "Zhang ping", 'M', 78.5};
struct Student *p = &stu;
/* 三種寫法完全等價 */
printf("%d\n", stu.num); // 1. 變數直接存取
printf("%d\n", (*p).num); // 2. 解參考再用 . (括號必要,. 優先級 > *)
printf("%d\n", p->num); // 3. 箭頭運算子(語法糖,最常用)
口訣:變數用 .,指標用 ->,(*p).member 記得加括號。
int n;
printf("輸入人數: ");
scanf("%d", &n);
struct Student *class = malloc(n * sizeof(struct Student));
if (!class) return 1;
for (int i = 0; i < n; ++i) {
class[i].name = malloc(20);
printf("姓名: "); scanf("%19s", class[i].name);
printf("學號 性別 成績: ");
scanf("%d %c %f", &class[i].num, &class[i].sex, &class[i].score);
}
/* 使用完畢釋放 */
for (int i = 0; i < n; ++i) free(class[i].name);
free(class);
#define MAX 100
struct Contact {
char name[20];
char phone[12];
};
int main() {
struct Contact book[MAX];
int n = 0, choice;
while (1) {
printf("\n1.新增 2.列印 3.查詢 4.離開: ");
scanf("%d", &choice);
if (choice == 4) break;
if (choice == 1) {
if (n >= MAX) { puts("已滿"); continue; }
printf("姓名: "); scanf("%19s", book[n].name);
printf("電話: "); scanf("%11s", book[n].phone);
++n;
} else if (choice == 2) {
for (int i = 0; i < n; ++i)
printf("%-20s %s\n", book[i].name, book[i].phone);
} else if (choice == 3) {
char key[20]; printf("查詢姓名: "); scanf("%19s", key);
for (int i = 0; i < n; ++i)
if (strcmp(book[i].name, key) == 0)
printf("找到: %s\n", book[i].phone);
}
}
return 0;
}
| 宣告 | 意義 | 記憶體圖示 |
|---|---|---|
struct Student *ps[10]; | 10 個指標的陣列,各自指向一個 Student | ps[0] → Studentps[1] → Student... |
struct Student (*pa)[10]; | 指向「10 個 Student 的陣列」的單一指標 | pa → [Student, Student, ...] |
struct Student arr[10];
struct Student *ps[10];
for (int i=0;i<10;++i) ps[i] = &arr[i]; // 指標陣列指向陣列元素
struct Student (*pa)[10] = &arr; // 指向整個陣列
(*pa)[3].num = 99; // 存取第 4 元素
void print_by_val(struct Student s) { // 複製整個結構體(含指標成員)
printf("%s\n", s.name);
}
void print_by_ptr(const struct Student *s) { // 僅複製指標,效率高、可加 const
printf("%s\n", s->name);
}
void modify_score(struct Student *s, float new_score) {
s->score = new_score; // 修改原物件
}
原則:結構體超過 16 bytes 或需修改內容 → 傳指標;小型唯讀結構體可傳值。
scanf("%s", stu.name) 若 name 是 char* 未配置記憶體 → 崩潰。改用 char name[20] 或 malloc。struct Student *p; p->num = 1; 未 malloc 直接解參考 → 野指標。free 順序:先釋放內部指標,再釋放結構體本身。typedef struct { ... } Student; 後直接用 Student 而非 struct Student。->,變數存取用 .。const struct T*,兼顧效率與安全。