指針是 C 語言的靈魂,也是初學者最大的攔路虎;結構體則讓我們能將異構數據聚合為邏輯實體。兩者結合,構成了系統級開發的基石。本文通過一個「員工信息文件解析」的完整案例,演示指針操作記憶體、結構體封裝數據、函數指針回調等核心技法。
指針本質是存儲記憶體地址的變量。通過地址「間接訪問」數據,是實現動態內存管理、高效參數傳遞、鏈表樹圖等複雜數據結構的前提。

圖1 指針間接訪問示意圖
打破陣列「同類型」限制,將工號、姓名、年齡等不同類型字段封裝為一個邏輯整體 T_EmployeeInfo。
程式 Pointer.c 讀取同目錄下的 EmployeeInfo.ini,每行格式為 工號|姓名|年齡,解析後輸出到控制台。

圖2 程序流程圖

圖3 文件內容存放示例
typedef struct {
UINT8 szEmployeeID[1024]; // 字串字段以 sz 開頭
UINT8 szEmployeeName[1024];
UINT32 iEmployeeAge; // 整型字段以 i 開頭
} T_EmployeeInfo;
最佳實踐: 統一命名前綴(sz/i)提升可讀性;字串緩衝區大小設為 1024,配合 MAX_RET_BUF_LEN 防止溢出。
GetValueFromStr這是本案例的精華:一個能根據分隔符、字段序號、目標類型,從源字串中提取並類型轉換的通用解析器。
BOOL GetValueFromStr(UINT16 iSerialNum, UINT8 iContentType,
UINT8 *pSourceStr, UINT8 *pDstStr,
UINT8 cIsolater, UINT32 iDstStrSize) {
// 步驟1:指針防護
if (pSourceStr == NULL) return FALSE;
// 步驟2:定位字段首尾指針 (strchr 查找分隔符)
UINT8 *pStrBegin = pSourceStr;
while (--iSerialNum != 0) {
pStrBegin = strchr(pStrBegin, cIsolater);
if (!pStrBegin) return FALSE;
pStrBegin++;
}
UINT8 *pStrEnd = strchr(pStrBegin, cIsolater);
if (!pStrEnd) return FALSE;
// 步驟3:長度保護與拷貝
UINT32 iFieldLen = pStrEnd - pStrBegin;
if (iFieldLen >= MAX_RET_BUF_LEN) iFieldLen = MAX_RET_BUF_LEN - 1;
memcpy(szRetBuf, pStrBegin, iFieldLen);
// 步驟4:根據類型轉換存儲 (switch + atoi)
switch (iContentType) {
case MML_STR_TYPE: strncpy(pDstStr, szRetBuf, iDstStrSize); break;
case MML_INT32_TYPE: *(UINT32*)pDstStr = (UINT32)atoi(szRetBuf); break;
// ... 其他類型
default: return FALSE; // 必須有 default 防禦
}
return TRUE;
}
關鍵技術點:
pStrEnd - pStrBegin 直接得字段長度,零拷貝定位。UINT8* 傳遞目標地址,內部根據 iContentType 強轉回 UINT32* 等寫入,實現泛型效果。default 分支,工業級代碼必備。FILE *hFile = fopen("EmployeeInfo.ini", "r"); // 只讀模式,防誤寫
while (fgets(szContentLine, sizeof(szContentLine), hFile)) {
// 逐行解析,調用 GetValueFromStr 填充結構體
// 注意:年齡為整型,傳址需 & 且強轉 (UINT8*)&t_EmployeeInfo.iEmployeeAge
}
fclose(hFile); // 必須配對關閉,釋放資源
fgets 自動處理換行符與 EOF,是行讀取的首選。
GetValueFromStr(3, MML_INT32_TYPE, szContentLine,
(UINT8 *)&(t_EmployeeInfo.iEmployeeAge), '|',
sizeof(t_EmployeeInfo.iEmployeeAge))
iSerialNum=3MML_INT32_TYPEszContentLine (字串名即首地址)&iEmployeeAge 取址 + (UINT8*) 強轉匹配參數類型'|' (單引號字符,非雙引號字串)按圖3準備文件,運行程式,正確輸出三位員工信息,驗證指針與結構體操作無誤。

圖4 正常測試輸出結果
fopen 失敗,輸出錯誤並退出。| 分隔符,strchr 返回 NULL,函數返回 FALSE,主流程捕獲並報錯。fgets 直接返回 NULL,循環不進入,程式靜默退出。
圖5 文件不存在時的輸出

圖6 分隔符缺失時的輸出

圖7 空文件時的輸出
GetValueFromStr 這類組件化設計,可復用於多種協議解析場景。「冰凍三尺,非一日之寒」。指針與結構體的熟練,來自於無數次「Segmentation Fault」後的反思與重構。願此文為你的 C 語言進階之路添一磚加一瓦。