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

C語言核心知識體系速查手冊:從編譯調試到內存模型的工程級總結

     編輯:C 語言入門

編譯與調試基礎

  • GCC 默認輸出 a.out,指定輸出:gcc -o myapp main.c
  • 調試信息宏(C99 標準):
    printf("FILE=%s, LINE=%d, FUNC=%s\n", __FILE__, __LINE__, __func__);
  • 編譯選項推薦:-Wall -Wextra -Wpedantic -std=c11 -g -O2

關鍵字分類速記 (C99/C11 共 37/44 個)

類別關鍵字
數據類型 (5)void char int float double
類型修飾 (4)short long signed unsigned
復雜類型 (5)struct union enum typedef sizeof
存儲類別 (6)auto static register extern const volatile
流程控制 (4)return continue break goto
分支結構 (5)if else switch case default
循環結構 (3)for do while
C99 新增 (5)inline restrict _Bool _Complex _Imaginary
C11 新增 (7)_Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local

基本類型尺寸對照表 (位數 = 字節 × 8)

類型32位系統64位系統 (LP64)備註
char11最小寻址單元
short22通常 16 位
int44自然字長
long48LP64 模型關鍵差異
long long88C99 保證 ≥64 位
指針48地址總線寬度/8
float44IEEE 754 單精度
double88IEEE 754 雙精度

工程鐵律:跨平台代碼必須使用 <stdint.h> 精確寬度類型(int32_t、uintptr_t、intmax_t 等)。

整數提升與常用算術轉換 (Usual Arithmetic Conversions)

double ← float
  ↑
long double (若存在)
  ↑
unsigned long long ← long long
  ↑
unsigned long ← long
  ↑
unsigned int ← int
  ↑
unsigned short ← short
  ↑
char (signed/unsigned) → int
  • 低精度向高精度提升,無符號優於有符號(同級)
  • 表達式類型由最高運算元決定
  • 陷阱:unsigned int + int → 無符號運算,負數變巨大正數

進制字面量前綴

  • 八進制:0 開頭(如 077 = 63)
  • 十六進制:0x/0X 開頭(如 0xFF = 255)
  • 二進制:0b/0B 開頭(GCC/Clang 擴展,C23 標準化)

負數存儲:二進制補碼

三步法:

  1. 絕對值寫二進制
  2. 按位取反(一補碼)
  3. 加 1(二補碼)
-7 (int32):
  7  = 0x00000007
  ~7 = 0xFFFFFFF8
  +1 = 0xFFFFFFF9  // 存儲值

printf("%#x\n", -7);  // 輸出 0xfffffff9

浮點數存儲:IEEE 754 格式

類型符號位指數位尾數位偏移量
float1823127
double111521023

示例 8.25 (float):

  1. 二進制:1000.01 = 1.00001 × 23
  2. 指數:3 + 127 = 130 = 10000010
  3. 尾數:00001 + 後補 0 至 23 位
  4. 組裝:0 10000010 00001000000000000000000 = 0x41040000

負數僅翻轉符號位:-8.25 = 0xC1040000

移位運算細節

  • << 左移:低位補 0,等價乘 2n(無符號保證,有符號溢出 UB)
  • >> 右移:
    • 無符號:邏輯右移,高位補 0
    • 有符號:算術右移(編譯器實現定義,主流保留符號位,高位補符號位)
-7 (0xFFFFFFF9) >> 4 = 0xFFFFFFF9 (算術右移,符號位擴展)
1000 (0x3E8) >> 4 = 0x3E (邏輯右移)

特殊運算符陷阱

運算符行為陷阱
&& / ||短路求值右側表達式可能不執行(副作用丟失)
^異或a^a=0、a^0=a、交換變量 a^=b^=a^=b (不可讀,勿用)
?:三目類型為兩操作數通用類型,副作用僅執行一次
,逗號左到右求值,整個表達式值為最右子表達式值
sizeof編譯期計算不求值表達式(sizeof(i++) 不會增 i)

printf 格式化輸出精要

  • 參數求值順序:右到左(調用約定),輸出順序:左到右
  • printf("%d,%d\n", i++, i); → 求值:右邊 i=10,左邊 i++=10 → 輸出 10,10
  • printf("%d,%d\n", i, i++); → 求值:右邊 i++=10 (i 變 11),左邊 i=11 → 輸出 11,10
  • 常用格式:%d/%i 有符號十進制,%u 無符號,%x/%X 十六進制,%o 八進制,%f/%e/%g 浮點,%c 字符,%s 字符串,%p 指針,%% 字面 %
  • 修飾符:%5d 寬度,%.3f 精度,%-10s 左對齊,%+d 強制符號,%08x 補零,%#x 前綴 0x

三大程序結構

  1. 順序:自上而下
  2. 選擇:if-else if-else、switch-case-default(表達式必為整型/字符型)
  3. 循環:
    • while:先判斷後執行
    • do-while:至少執行一次
    • for(init; cond; step):init→cond→body→step→cond...

跳轉:break 跳出當前循環/switch,continue 進入下一次迭代,return 退出函數,goto 標簽跳轉(慎用)。

變量存儲期與作用域

類別存儲期作用域鏈接性
普通局部塊執行期間塊內無
普通全局程序全期文件內(外部可見)外部
靜態局部 (static)程序全期塊內無
靜態全局 (static)程序全期文件內(內部鏈接)內部
extern 全局程序全期全程序(需聲明)外部
  • 局部遮蔽同名全局:內層 { int a=10; } 遮蔽外層 a
  • static 修飾函數:僅本文件可見(內部鏈接)

指針核心知識圖譜

聲明與基本操作

int a = 10;
int *p = &a;      // 取地址
int val = *p;     // 解引用讀取
*p = 20;          // 解引用寫入 (a 變 20)

指針類型 vs 指向類型

  • int *p:指針類型 int*,指向類型 int
  • 指針運算步長 = sizeof(指向類型)

野指針與空指針

  • 未初始化指針 = 野指針,極度危險
  • 初始化為 NULL (或 0、(void*)0) 表示「不指向有效對象」
  • 判空:if (!p) 優於 if (p == NULL)

指針運算

int arr[10];
int *p = &arr[0], *q = &arr[8];
p + 1;        // 向後偏移 1 個 int (4 字節)
p - q;        // 相差元素個數 (有符號,這裡為 -8)
(*p)++;       // arr[0] 值加 1,指針不變
*p++;         // 取 *p 值,然後 p 移向下一元素
*++p;         // p 先移動,再取值

void* 通用指針

  • 可接受任意對象指針賦值
  • 解引用前必須強轉:*(int*)p
  • 指針運算非法(指向類型大小未知)

字符串字面量 vs 字符數組

char *s = "hello";  // s 指向只讀區,不可修改 (*s='H' 崩潰)
char s[] = "hello"; // s 在棧上,可修改 (s[0]='H' 合法)

二級指針與指針數組

int a=10, *p=&a, **q=&p;  // q 指向 p,**q 即 a
char *argv[] = {"cmd", "arg1"};  // 指針數組
char **p = argv;  // 指向指針數組首元素

數組指針

int a[3][4];
int (*p)[4] = a;  // p 指向含 4 個 int 的數組 (即一行)
p+1;  // 跳過一行 (16 字節)

動態內存管理

函數原型特性
mallocvoid* malloc(size_t size)分配 size 字節,不初始化,失敗返 NULL
callocvoid* calloc(size_t n, size_t size)分配 n*size,歸零初始化,防溢出檢查
reallocvoid* realloc(void* ptr, size_t size)調整大小,可能移動內存,ptr 為 NULL 等同 malloc
freevoid free(void* ptr)釋放,ptr 為 NULL 安全無操作,雙重釋放 UB

模式:int *p = malloc(n * sizeof *p); if (!p) handle_err(); ... free(p); p = NULL;

const 與 volatile 進階

const int *p;       // p 指向常量,不可 *p=,可 p=
int *const p;       // p 是常指針,不可 p=,可 *p=
const int *const p; // 雙重 const

// 函數參數
void read_only(const int *p);  // 承諾不修改 *p
void mutate(int *const p);     // 承諾不改 p 指向 (少用)
  • 全局 const:只讀段,硬件保護,不可通過指針修改
  • 局部 const:棧上,編譯器優化為常量,但可通過指針修改 (僅有警告)
  • volatile:禁止優化,每次訪問真實內存/寄存器,用於硬件寄存器、中斷共享變量、信號處理

函數參數傳遞機制

  • 值傳遞:複製實參值,函數內修改不影響原變量
  • 地址傳遞:傳遞指針,函數內解引用修改影響原變量(模擬引用)
  • 數組傳遞:退化為指針,void f(int a[]) 等價 void f(int *a),sizeof(a) 為指針大小

sizeof 陷阱

int a = 10;
int arr[10] = {1,2,3};
char *s = "hello";

sizeof(a);    // 4 (int)
sizeof(arr);  // 40 (10*4)
sizeof(s);    // 4/8 (指針大小),非字符串長度
strlen(s);    // 5 (字符串長度,不含 \0)

// 函數參數退化
void f(int a[100]) { sizeof(a); }  // 4/8,a 是指針

字符串/數值轉換函數

  • atoi/atol/atoll:簡單轉換,錯誤返回 0,無法區分 "0" 和錯誤
  • strtol/strtoul/strtod:健壯解析,支持進制、尾指針返回、錯誤檢測 (errno)
  • sprintf/snprintf:格式化輸出到字符串,snprintf 防溢出
  • sscanf:從字符串解析,返回成功匹配項數

絕對地址訪問 (嵌入式/驅動)

#define REG32(addr) (*(volatile uint32_t*)(addr))
REG32(0x40020000) = 0x1;  // 寫寄存器
uint32_t val = REG32(0x40020004);  // 讀寄存器

這份手冊提煉了 C 語言工程實踐中最高頻、最高價、最易錯的核心知識點。建議收藏,遇到疑難雜癥時作為快速參考;更建議通讀 C11 標準草案 (N1570) 與 《C 專家編程》,建立系統性知識框架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved