首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言中級知識點總結:sizeof、結構體對齊、指針運算、記憶體分區、預處理陷阱

     編輯:關於C

前言

本文匯總 C 語言中級階段的核心知識點,涵蓋 sizeof 語義、結構體對齊規則、指針/陣列/函數指針複雜聲明、記憶體分區、堆使用四要素、預處理宏陷阱、頭檔管理、函數參數求值順序等,適合進階鞏固與面試速查。

一、sizeof 核心規則

  • **編譯期計算**,非函數,無運行開銷。
  • sizeof(型別) 需括號;sizeof 變數 括號可選,建議統一加。
  • sizeof(指針) = 指針大小(32位=4,64位=8),**不等於** 指向物件大小。
  • int a[5]; sizeof(a)=20(陣列大小);sizeof(&a)=4/8(指向陣列的指針大小)。
  • &a + 1 跳過整個陣列(型別 int(*)[5]),a + 1 跳過一個元素(型別 int*)。

二、結構體對齊三大鐵律

  1. **成員偏移**:每個成員偏移必須是 **min(成員大小, 對齊基數)** 的倍數(基數通常為編譯器選項 #pragma pack(n) 或預設 4/8)。
  2. **總大小對齊**:結構體總大小為 **max(最寬基本型別大小, 對齊基數)** 的整數倍,不足尾部填充。
  3. **巢狀結構體視為整體**:巢狀結構體作為成員時,其偏移按**自身對齊要求**對齊,大小計入外層總大小。

struct A { int i; double d; };      // sizeof=16 (i@0, d@8)
struct B { int i; struct A a; double d; }; // sizeof=32 (a@8 對齊8, d@24)

三、字串字面常數與轉義

  • 相鄰字串字面常數自動連接:"hello" "world" → "helloworld"。
  • 八進制轉義:\323 = 0xD3;\32"3 → \32 + '3'。
  • 十六進制轉義:\x60 = 0x60。

四、陣列下標與指針等價性

  • a[i] == *(a+i) == *(i+a) == i[a](交換律)。
  • 陣列名在**表達式**中退化為指向首元素的指針(int *const 屬性,不可修改指向)。
  • 二維陣列 int b[3][4]:b 型別 int(*)[4],b+1 跳過一行(16字節)。
  • *(*(b+2)+0) = b[2][0];*(b+2) = 第3行首地址;b+2 = &b[2][0]。

五、有符號/無符號運算陷阱

  • 混合運算時,**有符號隱式轉換為無符號**(整數提升規則)。
  • -1 > 0u 為真(-1 轉為巨大無符號數)。
  • 比較/列印時務必統一符號性,或顯式轉型。

六、記憶體五大分區(C++)/ 四大分區(C)

七、堆記憶體使用四要素(鐵律)


int *p = (int*)malloc(10 * sizeof(int));
if (p == NULL) return -1;      // 1. 必須檢查分配失敗
// ... 使用 p ...
free(p);                        // 2. 必須釋放
p = NULL;                       // 3. 必須置空防野指針
// 4. 不要重複 free,不要 free 非堆指針

八、指針進階:複雜聲明讀寫指南


typedef float (*PF)(int, double);     // 函數指針型別
int (*p)[3];                          // 指向 int[3] 的指針(二維陣列行指針)
int *ptr[3][4];                       // 二維指針陣列
int *(*ptr)[4];                       // 指向「4元素指針陣列」的指針
int (*myfun())(int*, int*);           // 返回函數指針的函數
int (*s[10])(int);                    // 10個函數指針的陣列

**右左法則**:從變數名出發,先右後左,遇括號反向,循環至解析完。

九、函數指針賦值與調用


void myfun(int x) { printf("%d", x); }
void (*pfun)(int) = myfun;   // 賦值:函數名即入口地址
pfun(10);                    // 調用方式1
(*pfun)(10);                 // 調用方式2(等價)

十、預處理宏陷阱與現代替代

  • 宏參數**副作用風險**:#define SQR(x) ((x)*(x)) → SQR(i++) 導致 i 增加兩次。
  • 宏無型別檢查、無作用域、除錯不可見。
  • **現代替代**:無參宏 → const / enum;有參宏 → inline 函數 / constexpr (C++)。
  • # 字串化:#define STR(x) #x → STR(abc) → "abc"。
  • ## 連接:#define CAT(a,b) a##b → CAT(var,1) → var1。

十一、頭檔管理鐵律

  1. **護衛宏**:#ifndef FILE_H #define FILE_H ... #endif。
  2. 頭檔**只聲明,不定義**(extern 變數、inline 函數、模板除外)。
  3. **< > vs ""**:系統頭檔用尖括號(搜尋系統路徑);專案頭檔用雙引號(先搜尋當前目錄)。
  4. 頭檔**不放大型 static 變數**(每個編譯單元產生一份拷貝,浪費空間且易誤用)。

十二、函數參數求值順序未定義

  • C 標準**不規定**參數求值順序(左→右、右→左、交錯皆合法)。
  • func(i++, i++) → **未定義行為**。
  • 鐵律:參數表達式**無副作用**,複雜計算先存入臨時變數再傳遞。

十三、總結

這 13 大知識點構成了 C 語言從「能跑」到「精通」的分水嶺。反覆閱讀、動手驗證(特別是結構體對齊、指針複雜聲明、宏副作用),將它們內化為直覺,是邁向系統級、嵌入式、高效能 C 開發者的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
區域C/C++ 共同C++ 額外典型內容
棧✓區域變數、函數參數、返回地址、幀指標
堆✓ (malloc/free)new/delete動態分配記憶體
全域/靜態✓全域變數、static 變數、字串字面常數
常量區✓字串字面常數、const 全域(可能合併只讀段)
自由存儲區new/deleteC++ 對象動態分配(與堆常重疊)