struct Student { int num; char *name; char sex; float score; };
struct Student stu = {101, "Zhang", 'M', 85.5};
struct Student *pstu = &stu; // 取結構體變量地址
// 錯誤:pstu = &Student; // 結構體標籤無地址
stu.num; // 1. 變量直接訪問
(*pstu).num; // 2. 解引用後訪問,括號必不可少
pstu->num; // 3. 箭頭運算符(推薦)
(*pstu).num 中括號不可省:*pstu.num 解析為 *(pstu.num),結構體指針無 num 成員,編譯錯誤。
struct Student class[5] = {...};
struct Student *ps = class; // ps 指向首元素
// ps+1 -> class[1], ps+i -> class[i]
for (ps = class; ps < class+5; ++ps) {
printf("%d %s %c %.1f\n", ps->num, ps->name, ps->sex, ps->score);
}
sizeof(struct Student),自動跨越整個結構體。ps = &class[0].score; 類型不匹配。結構體整體傳值會拷貝所有成員(含數組),開銷大。傳指針僅拷貝地址 (4/8 字節),且允許函數修改原數據。
void stats(struct Student *ps) {
float sum = 0; int fail = 0;
for (int i=0; i<5; ++i, ++ps) {
sum += ps->score;
if (ps->score < 60) ++fail;
}
printf("總分: %.1f, 平均: %.2f, 不及格: %d\n", sum, sum/5, fail);
}
int main() {
struct Student class[5] = {...};
stats(class); // 數組名退化為指針
return 0;
}
| 維度 | 值傳遞 void f(struct S s) | 指針傳遞 void f(struct S *p) |
|---|---|---|
| 參數拷貝 | 整個結構體(所有成員) | 僅地址 (4/8 字節) |
| 函數內修改 | 修改副本,不影響原值 | 修改原對象 |
| 性能 | 大結構體開銷大 | 極低開銷 |
| 只讀意圖 | 天然只讀 | 需 const struct S *p 表達 |
// 風格 1:索引 + 指針
for (int i=0; iscore
}
// 風格 2:純指針範圍
struct Student *end = ps + n;
for (; ps < end; ++ps) {
ps->score;
}
風格 2 更符合 C 風格,無索引變量,編譯器易優化。
struct Tag *ptr;,賦值取變量地址 &var。-> 最簡潔,(*p).m 需括號,*p.m 錯誤。const。