統測資電類・資訊科專業科目(二)核心考點

第 9 章:結構(struct)、typedef 與動態記憶體

本章統整統測程式設計中「複合資料型態」的核心工具:struct、typedef、記憶體對齊與malloc/free動態配置(111~115 年共計 7 題考古真題)。 出題老師最愛把「結構成員存取(. 與 ->)」、「sizeof與記憶體對齊」與「指標成員忘記額外配置記憶體」揉合在一起設計陷阱。 本教學將帶你掌握清晰的結構記憶體佈局概念,並透過7 題真題 + 5 題模擬題的所有選項深度剖析,徹底掃除所有答題盲點!

📦
7 大核心
結構與記憶體觀念全解構
🎯
7 題真題
111~115 統測題全收錄
💡
全選項剖析
A/B/C/D 逐項深入拆解
🚀
100% 互動
點擊即答 + 展開詳解

1 struct 基礎:把多種型態包成一個複合型態

struct 讓我們把多個不同型態的資料包成一個自訂的複合型態——可以想成一個「資料夾」,把姓名、分數這些原本各自獨立的變數,裝進同一個袋子裡打包管理。

C Code:定義並使用一個 struct
struct Student {
    int id;
    float score;
};

struct Student s1;          // 宣告一個Student結構變數
s1.id = 1;
s1.score = 88.5;
💡 struct 成員的型態沒有「必須互不相同」的限制

結構裡的成員可以是任意型態的組合,也完全可以包含多個相同型態的成員(例如兩個 int、三個 float 都合法)。struct 唯一的規則是:成員必須各自有不同的「名稱」,但型態不需要互不相同。

2 結構成員存取:. 與 -> 的選擇

存取結構成員的運算子要看手上拿的是什麼:若是「結構變數」本身,用 .(例如 student.score);若是「指向結構的指標」,則用 ->(例如 p->score,等同於 (*p).score)。

C Code:結構變數用 .,結構指標用 ->
Student s1;
s1.id = 1; s1.score = 88.5;    // 結構變數:用 .

Student *p = &s1;              // 結構指標:用 ->
p->score = 90.0;                // 等同於 (*p).score = 90.0;
手上拿的是該用哪個運算子範例
結構「變數」.s1.score
結構「指標」->p->score,等同 (*p).score
🧠 記憶口訣

「箭頭穿過指標,點點停在變數上」——看到 ->(箭頭),代表左邊那個東西是「指標」,箭頭幫你自動穿過去指向的位置;看到 .(點),代表左邊那個東西已經是「結構本身」,不需要再穿過任何東西。

3 typedef:幫複雜的型態取一個簡短的別名

typedef 可以幫複雜的型態(尤其是 struct)取一個簡短的別名,之後就能直接用這個別名當作型態名稱來宣告變數,不需要每次都重複寫冗長的 struct 結構名稱。

C Code:typedef struct 的兩種常見寫法
// 寫法一:匿名結構直接取別名
typedef struct {
    int id;
    float score;
} Student;
Student s1;                  // 直接用Student宣告,不用寫struct

// 寫法二:結構有自己的標籤(tag),同時再取一個別名
typedef struct studentScore {
    int id;
    float score;
} SCORE;
SCORE student[50];           // 用別名SCORE宣告一個結構陣列
struct studentScore s2;      // 也可以繼續用原本的標籤搭配struct宣告
⚠️ 別把「型態別名」跟「變數名稱」搞混

SCORE 是一個型態名稱(typedef定義出來的別名),不是變數,不能對它做索引 SCORE[27] 或用 . 存取成員;真正拿來存放資料、可以用索引或 . 存取的,是用這個型態宣告出來的變數(例如 student)。

4 sizeof(struct) 與記憶體對齊(alignment)

sizeof(struct) 常常會大於各成員大小直接相加的總和,原因是記憶體對齊(alignment):CPU讀取記憶體時,某些型態(尤其是指標)習慣從特定倍數的位址開始讀取效率才高,編譯器會在成員之間自動插入一些沒有用到的「補位(padding)」位元組,讓每個成員都乖乖對齊到適合的位址。

C Code:CLASS 結構因記憶體對齊多出的空間(64位元系統)
typedef struct class_st {
    int id;         // 4 bytes
    char *name;     // 8 bytes(64位元指標)
    float score;    // 4 bytes
} CLASS;
// 直接相加:4+8+4=16 bytes
// 但 sizeof(CLASS) 實際上是 24 bytes(因為對齊而插入了padding)
位移(offset)內容說明
0~3int id佔4 bytes
4~7(padding)補4 bytes,讓下一個指標成員從8的倍數位址開始
8~15char *name佔8 bytes(64位元指標)
16~19float score佔4 bytes
20~23(padding)補4 bytes,讓整個struct大小是8的倍數(24)
🧠 常考數值(64位元 x86 系統)

sizeof(int)=4、sizeof(char)=1、sizeof(任何指標型態)=8(不管是 int*、char* 還是其他型態的指標,因為指標存放的都是位址,位址在64位元系統上固定佔8 bytes)。sizeof(結構陣列) 則是「單一結構大小 × 元素個數」。

5 malloc() 動態配置記憶體與 free()

malloc() 會在程式執行期間依需要的大小向系統要一塊記憶體,回傳指向這塊記憶體的指標;這塊記憶體不會自動消失,程式用完後要自己呼叫 free() 歸還,否則會造成記憶體洩漏。

C Code:malloc() 動態配置一個結構、用完 free()
#include <stdlib.h>
typedef struct { int id; float score; } Record;

Record *r = (Record *)malloc(sizeof(Record));
r->id = 1;
r->score = 95.5;
printf("id=%d score=%.1f\n", r->id, r->score);
free(r); // 用malloc配置的記憶體,使用完務必呼叫free()釋放,避免記憶體洩漏
💡 malloc() 只會配置「你要求的大小」

malloc(sizeof(Record)) 精確配置了剛好能容納一個 Record 結構的空間,不多也不少。這個特性在下一節會延伸出一個統測最愛的陷阱。

6 結構裡的指標成員:malloc 不會連帶配置它指向的空間

如果結構裡有指標成員(如 char *name),malloc(sizeof(CLASS)) 只會配置結構本身的空間(包含足夠存放 name 這個指標「位址值」本身的空間),並不會連帶替這個指標配置到它未來要指向的字串空間。這是統測結構題最愛出的陷阱。

C Code:忘記替指標成員額外配置記憶體(危險示範)
typedef struct { int id; char *name; float score; } CLASS;
CLASS *c = (CLASS *)malloc(sizeof(CLASS));  // 只配置了CLASS本身
c->id = 1;
strcpy(c->name, "Brown");  // ❌ 危險!c->name還沒有指向任何有效的記憶體
// c->name此時是「野指標」,往它寫入資料是未定義行為
C Code:正確做法——額外再 malloc 一次給指標成員
CLASS *c = (CLASS *)malloc(sizeof(CLASS));
c->id = 1;
c->name = (char *)malloc(20 * sizeof(char));  // ✅ 額外配置name指向的字串空間
strcpy(c->name, "Brown");                     // 現在才是安全的寫入
⚠️ 統測必考陷阱:兩層記憶體要配置兩次

結構本身是「第一層」記憶體,靠一次 malloc(sizeof(CLASS)) 就能配置好;但結構裡的指標成員所指向的內容是「第二層」,需要再額外呼叫一次 malloc 才能安全使用,兩者是獨立的兩塊記憶體,缺一不可。

7 結構陣列:管理多筆記錄

結構陣列讓我們用同一個型態一次管理多筆資料(例如全班的學生資料),每個元素都是一份完整、獨立的結構,用 . 存取各自的成員。

C Code:用結構陣列儲存多筆記錄
typedef struct { char name[10]; int score; } Student;

Student list[2] = { {"Amy", 88}, {"Ben", 92} };
for (int i = 0; i < 2; i++)
    printf("%s: %d\n", list[i].name, list[i].score);
🖥️ 終端機執行輸出結果
Amy: 88
Ben: 92
💡 統測愛考題型:用結構陣列取代多個平行陣列

如果需要記錄「每一筆資料都有好幾種屬性」(例如每隻寵物都有名字、出生年、性別、體重),用一個結構陣列(每個元素是一份完整記錄)遠比用好幾個各自獨立的陣列(name陣列、birth_year陣列……)來得正確又好維護,尤其是像「中文名字」這種本身就需要好幾個字元才能存放的欄位,單一個字元陣列只能存一筆,無法對應到100筆各自不同的名字。

8 111~115 歷屆統測真題全選項深度剖析(共 7 題)

以下收錄統測專業科目(二)近年全部 7 題結構、typedef與動態記憶體真題。每題均提供高解析度原始考題掃描圖、互動選項按鈕與所有選項逐項深入解析:

111 統測專二 Q50 📌 概念:結構(structures)觀念辨析
試題來源:技專校院入學測驗中心
關於C語言中結構(structures)資料型態的敘述,下列何者錯誤?
111 統測專二 Q50 題目截圖
本題標準答案: (C) 定義結構只能使用不同資料型態的變數

🔍 四個選項逐項深度剖析

選項 A 敘述本身正確(不是本題答案)
struct 確實是 C 語言讓使用者能自行定義新的複合資料型態的機制,可以把多個不同型態的資料組合成一個新型態,這句話正確描述了 struct 的性質。
選項 B 敘述本身正確(不是本題答案)
要宣告一個結構型態的變數,必須先用 struct 定義好這個結構的名稱與成員,才能拿這個已定義好的結構名稱來宣告變數,不能無中生有宣告一個沒定義過的結構型態,這句話正確描述了語法規則。
正確答案完整推導(★ 本題要找的錯誤敘述)
struct 的成員變數之間並沒有「型態必須互不相同」的限制,一個結構完全可以包含多個相同型態的成員(例如兩個 int 成員、三個 float 成員都合法)。這句話錯誤地限制了 struct 的用法,是本題要找的錯誤敘述,選 (C)。
選項 D 敘述本身正確(不是本題答案)
C 語言定義結構確實只能使用 struct 關鍵字(C 語言沒有像 C++ 那樣可以用 class 關鍵字定義結構),這句話正確描述了 C 語言的語法規則。
113 統測專二 Q43 📌 概念:typedef/結構(struct)陣列存取
試題來源:技專校院入學測驗中心
假設班上共N個學生,第i個學生的資料儲存在student[i-1]裡。若要取得學號28的學生成績放到sscore,下列程式碼何者正確?
題幹程式碼
#include <stdio.h>
#define N 50
void main(){
    typedef struct studentScore {
        int id;      //學號
        float score; //成績
    } SCORE;
    SCORE student[N], *p;
    float sscore;
    p = student+28;
    ...
113 統測專二 Q43 題目截圖
本題標準答案: (A) sscore = student[27].score;

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
學號28的學生資料存於 student[28-1]=student[27]。student 是結構陣列,取用其 score 成員應以 . 運算子存取,即 student[27].score,選 (A)。
選項 B 錯誤解析
SCORE 是型態名稱(typedef定義的別名),不是變數,不能對一個型態名稱做索引 [27] 或用 . 存取成員;student 才是真正的結構陣列變數,這個選項把型態名稱跟變數名稱的角色完全弄反了,語法不合法。
選項 C 錯誤解析
student 是一個結構「陣列」,不是指標,不能用 -> 運算子存取(-> 是給指標用的,陣列要用 . 搭配索引);而且 score[27] 也是錯的寫法——score 是單一 float 成員,不是陣列,不能對它取索引。
選項 D 錯誤解析
除了跟選項C同樣有 -> 和 score[29] 索引語法錯誤的問題,索引數字29對應到的其實會是學號30的資料(student[29]對應學號30),跟題目要求的學號28(對應student[27])也不符。
113 統測專二 Q44 📌 概念:排序演算法(泡沫排序)/迴圈比較次數計算
試題來源:技專校院入學測驗中心
使用泡沫排序演算法將student陣列的成績score排序時,需經幾次成績數值比較,可得排序結果?(背景同上題,共N=50筆資料)
113 統測專二 Q44 題目截圖
本題標準答案: (B) 1225

🔍 四個選項逐項深度剖析

選項 A(50)錯誤解析
此答案很可能誤以為比較次數等於資料筆數本身(N=50),忽略了泡沫排序是「每一筆資料都要跟其他每一筆資料做兩兩比較」,比較的總次數遠不只等於資料筆數。
正確答案完整推導(★ 本題標準答案)
標準泡沫排序對n筆資料排序,兩兩比較總次數是一個等差數列求和:第1輪比較(n-1)次,第2輪比較(n-2)次,……最後一輪比較1次,總和為 n(n-1)/2。n=N=50,故比較次數為 50×49/2=1225,選 (B)。
選項 C(24550)錯誤解析
這個數字量級明顯偏大,可能是在推算比較次數的過程中,把「應該隨著排序進行而逐輪遞減的比較範圍」誤算成了固定不變、甚至疊加放大的次數,反映對泡沫排序「每一輪需要比較的範圍會遞減」這個特性不熟悉。
選項 D(245050)錯誤解析
這個數字的量級更大,可能是把比較次數跟其他不相關的數值(例如資料值本身、或是更高次方的估算)混在一起計算,明顯偏離了正確的等差數列求和公式 n(n-1)/2。
114 統測專二 Q46 📌 概念:結構與指標/動態記憶體配置(指標成員陷阱)
試題來源:技專校院入學測驗中心
程式編譯後執行時無法輸出字串Brown,其發生的原因為何?
題幹程式碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct class_st {
    int id;
    char *name;
    float score;
} CLASS;
CLASS *class;
int main(){
    class = (CLASS *)malloc(sizeof(CLASS));
    (*class).id = 1;
    strcpy((*class).name, "Brown");
    printf("%s", class->name);
    return 0;
}
114 統測專二 Q46 題目截圖
本題標準答案: (A) (*class).name沒有指向已配置的記憶體空間

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
malloc(sizeof(CLASS)) 只配置了 CLASS 結構本身(含 name 這個指標欄位所佔的位元組空間,用來存放一個位址),並沒有替 name 指標另外配置它「所指向」的字串緩衝區。(*class).name 此時是一個未初始化的野指標,strcpy 試圖把 "Brown" 寫入這塊無效、未配置的記憶體,會導致未定義行為,選 (A)。
選項 B 錯誤解析
class 本身是指標變數(CLASS *class),class.name 這種寫法對指標使用 . 運算子是不合法的語法,指標必須用 -> 或先解參考 (*class) 再用 .;這個選項提出的修改方式本身就無法通過編譯,也沒有解決 name 指標未配置記憶體的根本問題。
選項 C 錯誤解析
class->name 與 (*class).name 是完全等價的兩種寫法,printf 使用哪一種寫法都不影響結果;問題根本不在 printf 使用哪種存取語法,而在於 name 指標從一開始就沒有指向任何有效的、已配置好的記憶體空間。
選項 D 錯誤解析
指標變數 class 宣告為全域或區域變數,跟 name 指標有沒有被配置到有效記憶體是兩個完全獨立的問題;把 class 改成區域變數並不會讓 name 指標自動獲得它所需要的字串緩衝區,無法解決程式無法輸出的根本原因。
114 統測專二 Q49 📌 概念:sizeof運算子/基本資料型態大小
試題來源:技專校院入學測驗中心
(64位元x86電腦)關於變數m, n, p數值的大小,下列不等式何者正確?
題幹程式碼
typedef struct class {
    int id; char *name; float score;
} CLASS;
CLASS classB[49];
int main(){
    CLASS *pC, classA[50], classB[60];
    int i=10, *pi, m, n, p, a, b, c, d, e, f, g;
    m=sizeof(int); n=sizeof(char); p=sizeof(int *);
    a = sizeof(classA);  b = sizeof(classB[59]);
    c = sizeof(pC);      d = sizeof(i);
    e = sizeof(&i);      f = sizeof(pi);
    g = sizeof(CLASS);
}
114 統測專二 Q49 題目截圖
本題標準答案: (B) m≧n

🔍 四個選項逐項深度剖析

選項 A(m<n<p)錯誤解析
代入實際數值 m=4, n=1, p=8,m<n(4<1)明顯不成立,這個不等式關係整個方向反了——實際上 m(4) 遠大於 n(1),不是小於。
正確答案完整推導(★ 本題標準答案)
m=sizeof(int)=4;n=sizeof(char)=1;p=sizeof(int *)=8(64位元系統上指標固定佔8 bytes)。逐一檢驗選項:m≧n 即 4≧1 成立,選 (B)。
選項 C(m>n>p)錯誤解析
前半段 m>n(4>1)成立沒錯,但後半段 n>p(1>8)不成立——n(1) 遠小於 p(8),不是大於,這個不等式在後半段方向反了。
選項 D(p≦n)錯誤解析
代入實際數值,p≦n 即 8≦1 明顯不成立,p(8) 遠大於 n(1),不是小於等於,這個不等式的方向也反了。
114 統測專二 Q50 📌 概念:sizeof運算子/結構與記憶體對齊(背景同上題)
試題來源:技專校院入學測驗中心
下列變數何者的數值最大?
114 統測專二 Q50 題目截圖
本題標準答案: (A) a

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
CLASS 結構含 int id(4 bytes)+char *name(8 bytes指標,因對齊在前面補4 bytes padding)+float score(4 bytes),sizeof(CLASS)=g=24 bytes。a=sizeof(classA),classA 是 main() 內宣告的CLASS結構陣列共50個元素,故 a=50×24=1200,選 (A)。
選項 B(sizeof(classB[59]))錯誤解析
classB[59] 只是陣列中「單一一個元素」,並不是整個陣列,它的大小就等於單一個 CLASS 結構的大小24 bytes(跟g相同),遠小於代表整個50個元素陣列大小的 a=1200。
選項 C(sizeof(CLASS))錯誤解析
g 只是單一個 CLASS 結構本身的大小(24 bytes,包含記憶體對齊的padding),並不是整個陣列的大小,比 a 小很多。
選項 D(sizeof(i))錯誤解析
i 只是一個單純的 int 變數,大小固定是4 bytes,是四個選項中數值最小的,遠不如 a 的1200。
115 統測專二 Q50 📌 概念:結構(struct)陣列 vs 平行陣列的設計選擇
試題來源:技專校院入學測驗中心
曉智想設計一個C語言程式記錄毛小孩資訊,每隻毛小孩都有中文名字、出生年份、性別和體重四種資料。下列何者可以記錄最多100隻毛小孩的資訊?
115 統測專二 Q50 題目截圖
本題標準答案: (C) struct pet{ char name[100]; int birth_year; char gender; float weight; }Pets[100];

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
name[100] 只是「一個」字元陣列(一個字串),最多只能存放一隻毛小孩的名字,並不是100個獨立的名字欄位;其餘三個陣列雖然各自能存100筆資料,但name無法對應存放100隻毛小孩各自的名字,整體來說無法完整記錄100隻毛小孩的資訊。
選項 B 錯誤解析
跟選項A同樣的問題,name[20] 依然只是「一個」字元陣列(一個字串),只能存放一隻毛小孩的名字,即使長度縮短成20也沒有改變它只能存一筆名字資料的本質,無法對應100隻毛小孩各自不同的名字。
正確答案完整推導(★ 本題標準答案)
先用 struct pet{...} 定義好一隻毛小孩需要的四項資料打包成一個結構型態,再宣告 Pets[100] 為這個結構的陣列,每個陣列元素 Pets[i] 都是一份完整、獨立的毛小孩資料(各自的name、birth_year、gender、weight),可以正確地各自儲存100隻毛小孩完整的四項資訊,選 (C)。
選項 D 錯誤解析
struct pet[100]{...} 這種語法不合法,C 語言不能在定義struct標籤(宣告結構型態的當下)直接於標籤名稱後面接上陣列大小 [100],陣列大小必須接在「變數名稱」後面(如選項C的 Pets[100]),這是編譯不會通過的語法錯誤。

9 高職段考與模擬精選實戰題(5 題全選項解析)

透過以下 5 題精選模擬試題,全面檢驗你對struct基礎、成員存取、typedef、記憶體對齊與malloc的掌握度:

模擬實戰第 1 題 📌 概念:struct 成員可以是相同型態
已知下列 C 語言程式碼片段,執行後印出的內容為何?
C Code
struct Point {
    int x;
    int y;
};
struct Point p1 = {3, 4};
printf("%d %d", p1.x, p1.y);
本題標準答案: (A) 3 4

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
struct 的成員之間並沒有型態必須互不相同的限制,Point 結構的 x 跟 y 都是 int 型態完全合法。用大括號依序初始化,p1.x=3, p1.y=4,用 . 運算子直接存取印出 "3 4",選 (A)。
選項 B 錯誤解析
這是對 struct 規則的誤解,struct 完全允許包含多個相同型態的成員,這不是 C 語言的語法限制,程式可以正常編譯執行。
選項 C(4 3)錯誤解析
把 x 跟 y 的值弄反了,初始化列表 {3,4} 是依照成員宣告順序對應賦值,第一個值3對應第一個宣告的成員x,第二個值4對應第二個宣告的成員y,不會自動對調。
選項 D(0 0)錯誤解析
誤以為 {3,4} 這種初始化語法沒有真正生效,但 p1 確實透過大括號初始化被賦予了3和4這兩個值,不會維持0。
模擬實戰第 2 題 📌 概念:結構變數(.)與結構指標(->)存取同一份資料
已知下列 C 語言程式碼片段,執行後印出的內容為何?
C Code
struct Book { char title[20]; int pages; };
struct Book b1 = {"C Programming", 300};
struct Book *pb = &b1;
printf("%d %d", b1.pages, pb->pages);
本題標準答案: (A) 300 300

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
b1 是結構變數,用 . 存取 b1.pages 得到300;pb 是指向b1的結構指標,用 -> 存取 pb->pages,等同於 (*pb).pages,同樣取得b1的pages成員,也是300。兩種存取方式指向同一份資料,結果自然相同,選 (A)。
選項 B(300 0)錯誤解析
誤以為 pb->pages 這種指標存取方式沒有正確取得b1實際的值。但 pb 明確是透過 &b1 指向b1,pb->pages 就是在存取 b1.pages 這同一塊記憶體,結果必然一致,不會是0。
選項 C 錯誤解析
. 用在結構變數、-> 用在結構指標都是完全合法的標準C語法,這段程式碼可以正常編譯執行,並沒有語法錯誤。
選項 D(0 300)錯誤解析
跟選項B相反地誤判了哪一個存取方式會出錯,同樣是對 . 與 -> 都能正確存取到同一份資料這個事實的誤解。
模擬實戰第 3 題 📌 概念:typedef struct 匿名結構用法
已知下列 C 語言程式碼片段,執行後印出的內容為何?
C Code
typedef struct { int day, month, year; } Date;
Date today = {18, 8, 2026};
printf("%d/%d/%d", today.month, today.day, today.year);
本題標準答案: (A) 8/18/2026

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
typedef struct {...} Date; 定義了一個匿名結構,並直接把型態別名取為Date,之後可以直接用Date當作型態名稱宣告變數。today 依初始化列表依序對應 day=18, month=8, year=2026。printf 依引數順序印出 today.month(8)、today.day(18)、today.year(2026),得 "8/18/2026",選 (A)。
選項 B 錯誤解析
這個答案把printf引數的順序看反了,程式碼裡printf的引數順序明確是 today.month, today.day, today.year(先印month再印day),不能自行對調。
選項 C 錯誤解析
typedef struct {...} Date; 是完全合法的typedef+匿名結構寫法,這正是typedef最常見的用途——讓使用者之後可以直接用Date這個簡短的別名宣告變數,不需要每次都寫冗長的 struct 結構名稱,不會產生編譯錯誤。
選項 D 錯誤解析
這個答案把printf引數的順序也看錯了,變成按照year, month, day的直覺順序輸出,但程式碼裡printf明確寫的引數順序是month, day, year,必須照程式碼實際的順序輸出。
模擬實戰第 4 題 📌 概念:sizeof(struct) 因記憶體對齊而大於成員總和
已知下列 C 語言程式碼片段,執行後印出的內容為何?
C Code
struct Mix {
    char c;
    int n;
};
printf("%d", sizeof(struct Mix) >= sizeof(char) + sizeof(int));
本題標準答案: (A) 1

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
struct Mix 包含一個char(1 byte)跟一個int(通常需要4-byte對齊),編譯器通常會在char後面補上padding,讓int能從4的倍數位址開始,因此 sizeof(struct Mix) 通常會是8 bytes,大於單純把成員大小相加的 1+4=5 bytes。所以判斷式為真(非0),printf印出1,選 (A)。
選項 B(0)錯誤解析
這個答案誤以為 struct 的大小就是把所有成員大小直接相加、沒有任何額外的padding空間,忽略了記憶體對齊經常會讓struct的實際大小大於成員大小的總和,判斷式應該為真,不會是0。
選項 C(5)錯誤解析
printf("%d", 判斷式) 印出的是判斷式的「真假結果」(1或0),不是 sizeof(char)+sizeof(int) 這個總和本身的數值,這個答案誤把要印出的內容當成了純粹的大小總和。
選項 D(8)錯誤解析
同樣的誤解,這個答案把要印出的內容誤看成是 sizeof(struct Mix) 本身的數值,但程式碼裡printf要印的是一個比較判斷式(>= 運算的結果,只會是1或0),不是某個sizeof的原始數值。
模擬實戰第 5 題 📌 概念:正確替結構的指標成員額外配置記憶體
已知下列 C 語言程式碼片段,執行後印出的內容為何?
C Code
typedef struct { char *msg; } Note;
Note *n = (Note *)malloc(sizeof(Note));
n->msg = (char *)malloc(20 * sizeof(char));
strcpy(n->msg, "Hi");
printf("%s", n->msg);
本題標準答案: (A) Hi,正常輸出

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
這段程式碼做對了114年Q46錯誤示範中缺少的那一步:先用 malloc(sizeof(Note)) 配置Note結構本身的空間,接著額外再呼叫一次malloc,特別替 n->msg 這個指標配置了20個字元的緩衝區,讓它真正指向一塊有效、可以寫入的記憶體,之後strcpy才能安全地把"Hi"複製進去,printf正常輸出"Hi",選 (A)。
選項 B 錯誤解析
這正是「忘記替指標成員額外配置記憶體」時才會發生的問題(如同114年Q46的錯誤示範),但本題程式碼已經正確地呼叫了兩次malloc——一次配置Note結構本身,一次額外配置msg指標指向的字串緩衝區,並不會發生野指標寫入的問題。
選項 C 錯誤解析
這段程式碼的語法完全正確(假設已include stdlib.h與string.h),兩次malloc、strcpy、printf的用法都合乎標準C語法,不會有編譯錯誤。
選項 D 錯誤解析
strcpy(n->msg, "Hi") 確實把"Hi"(連同結尾的'\0')複製進了msg指向的緩衝區,msg並不是空字串,printf會正常印出"Hi"這兩個字元,不會是空字串。

10 考前衝刺 10 秒速記口訣 & 核心知識檢核清單

✅
struct 成員型態無限制
結構成員可以是任意型態組合,完全允許多個相同型態的成員。
✅
. 與 -> 口訣
「箭頭穿過指標,點點停在變數上」——結構變數用.,結構指標用->。
✅
typedef 是別名,不是變數
型態別名(如SCORE)不能被索引或用.存取,真正的結構陣列變數才可以。
✅
記憶體對齊會讓 sizeof 變大
sizeof(struct)常大於成員大小總和,因編譯器插入padding對齊指標等成員。
✅
指標成員要配置兩次記憶體
malloc(sizeof(結構))只配置結構本身,指標成員指向的空間要再malloc一次。
✅
malloc 用完要 free
動態配置的記憶體不會自動釋放,用完務必呼叫free()歸還,避免記憶體洩漏。
✅
結構陣列優於平行陣列
記錄多筆、多欄位的資料時,一個結構陣列比好幾個各自獨立的陣列更正確好維護。