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

C 語言基礎核心知識點大全:從 printf 到檔案操作

     編輯:關於C

前言:C 語言「坑」點彙總,建立正確心智模型

C 語言看似簡單,實則細節決定成敗。本文彙整 29 個核心知識點,涵蓋輸入輸出、字串、函式、記憶體、指標、陣列、結構體、位運算、檔案操作等,幫你建立正確的心智模型,避開常見陷阱。

一、輸入輸出與格式化

1. printf 參數求值順序:右到左,輸出左到右

int x = 5;
printf("%d %d %d", x, ++x, ++x);  
// VC6.0 / GCC (舊版) 輸出: 7 7 6
// GCC (新版) / Clang 輸出: 7 7 7 (未定義行為,勿依賴)
// ✅ 正解:不要在同一表達式中多次修改同一變數

標準規定:函式參數求值順序未定義,跨編譯器、跨版本、跨最佳化等級皆可能不同。

2. 格式寬度與對齊

  • %md:寬度 m,不足左補空格,超寬按實際輸出
  • %-md:左對齊,不足右補空格

二、字元與字串操作

3. 數字轉字元:'0' + m

int m = 5; char c = '0' + m;  // c == '5'

4. 小寫轉大寫:c - 'a' + 'A' (僅適用 ASCII)

char c = 'h'; char upper = c - 'a' + 'A';  // 'H'

5. switch 穿透特性:無 break 則貫穿執行後續 case

switch (x) {
    case 1: puts("one");
    case 2: puts("two");  // x==1 時也會印出 "two"
    default: puts("other");
}

6. 字串結束符 \0 佔一個位元組

char str[5] = "china";  // ❌ 需 6 位元組: 'c','h','i','n','a','\0'
char str[6] = "china";  // ✅

7. 輸入函式差異

函式空白處理緩衝區溢出風險備註
scanf("%s", str)遇空白/換行停止高 (無長度限制)不安全
gets(str)讀整行含空白極高 (已移除 C11)禁用
fgets(str, n, stdin)讀 n-1 字元或遇 \n無 (指定長度)✅ 推薦

8. 字串函式速查

strcpy(dest, src)      // 複製含 \0,dest 需足夠空間
strncpy(dest, src, n)  // 複製 n 字元,不足補 \0,超長不加 \0 ⚠️
strcat(dest, src)      // 追加,dest 需足夠空間
strncat(dest, src, n)  // 追加 n 字元
strcmp(s1, s2)         // 比較,相等 0,s1>s2 正數,s1

三、函式與參數傳遞

9. 單向值傳遞:形參改變不影響實參

void swap(int a, int b) { int t=a; a=b; b=t; }  // ❌ 無效
void swap(int *a, int *b) { int t=*a; *a=*b; *b=t; }  // ✅ 傳址

10. 陣列作為參數:退化為指標

void func(int arr[]) { }        // 等價於 int *arr
void func(int arr[10]) { }      // 長度資訊丟失,仍為 int *arr
void func(int (*arr)[5]) { }    // 二維陣列:保留第二維,退化為指向陣列的指標

四、變數儲存類別與生命週期

儲存類別關鍵字儲存區生命週期作用域預設初值
自動 (區域)(無)/auto堆疊函式呼叫期間區塊不定值 (垃圾值)
靜態區域static靜態區程式全程區塊0
靜態全域static (檔案層級)靜態區程式全程檔案 (內部連結)0
外部全域extern (預設)靜態區程式全程全程式 (外部連結)0
暫存器registerCPU 暫存器/堆疊同 auto區塊不定值

11. static 區域變數:只初始化一次,跨呼叫保持值

void f() {
    static int a = 0;  // 編譯期初始化 0,只執行一次
    printf("%d ", ++a);
}
f(); f(); f();  // 輸出: 1 2 3

五、指標與陣列進階

12. 運算子優先級與結合性

  • []、()、.、-> 最高,左結合
  • *、&、++、-- (前綴/後綴) 次高,右結合
  • *p++ ≡ *(p++) (取值後指標遞增)
  • *++p ≡ *(++p) (指標遞增後取值)

13. 二維陣列記憶體佈局:行優先

int a[2][3] = {{1,2,3},{4,5,6}};
// 記憶體: 1 2 3 4 5 6
// a       → 第 0 行首址
// a+1     → 第 1 行首址 (跨過 3 個 int)
// *a / a[0] → a[0][0] 址
// *(a+1) / a[1] → a[1][0] 址

14. 陣列指標 vs 指標陣列

int (*p)[4];  // 陣列指標:指向含 4 個 int 的陣列 (行指標)
int *p[4];    // 指標陣列:含 4 個 int* 的陣列

15. 字串輸入必須先配置空間

char *cp; scanf("%s", cp);  // ❌ 野指標,崩潰
char buf[20]; scanf("%s", buf);  // ✅
char *cp = malloc(20); scanf("%s", cp);  // ✅

六、結構體、共用體、列舉

16. 結構體初始化:僅定義時可用大括號

struct Student { int id; char *name; };
struct Student s1 = {1, "Tom"};  // ✅ 定義時初始化
struct Student s2; s2 = {2, "Jerry"};  // ❌ 定義後不可用大括號
// 定義後需逐欄位賦值: s2.id=2; s2.name="Jerry";

17. 共用體:同一記憶體,同一時間只有一個成員有效

  • 大小 = 最大成員大小 (對齊後)
  • 不可作為函式參數/回傳值 (C89),C99 允許
  • 常用於型別雙關、位欄位、省記憶體

18. 列舉:預設從 0 遞增

enum Color { RED, GREEN, BLUE };  // RED=0, GREEN=1, BLUE=2
enum Color c = RED; int i = RED;  // i == 0

七、typedef 型別別名

typedef int INTEGER;
typedef struct { int num; char name[10]; float score; } Student;
Student s1, s2, *ps;

typedef 不創建新型別,僅為現有型別起別名。

八、位運算與移位

19. 位運算規則:補碼參與運算,符號位參與

  • & (AND)、| (OR)、^ (XOR)、~ (NOT)
  • XOR 性質:a^a=0、a^0=a、a^~a=-1 (全 1)
  • 無暫存器交換:a^=b; b^=a; a^=b;

20. 移位運算:實作定義 (Implementation-defined)

類型左移右移
邏輯移位低位補 0高位補 0
算術移位低位補 0高位補符號位 (保持正負)
循環移位移出的位移入另一端同上

C 標準未規定有號數右移行為,**x86/MSVC/GCC 通常採算術移位**,但不可攜帶假設。無號數右移保證邏輯移位 (補 0)。

⚠️ 移位不改變原變數:a >> 2 產生新值,a 不變;需 a = a >> 2 才改變。

九、檔案操作 (FILE*)

21. FILE 結構體:標準庫不透明型別

typedef struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; ... } FILE;

22. 開檔模式

模式說明建檔截斷讀寫位置
r唯讀否否開頭
w唯寫是是開頭
a附加是否末尾
r+讀寫否否開頭
w+讀寫是是開頭
a+讀寫附加是否末尾

二進位模式加 b:rb, wb, ab... (Windows 區分換行轉換,Linux/Unix 無差異)

23. 緩衝區與資料完整性

  • 預設全緩衝 (通常 4KB/8KB),行緩衝 (終端機),無緩衝 (stderr)
  • 異常終止會丟失緩衝區資料,必須 fclose() 或 fflush() 強制寫入
  • fclose(fp) 回傳 0 表成功,EOF 表失敗

24. 檔案讀寫函式族

// 字元
int fgetc(FILE*); int fputc(int, FILE*);
// 字串 (含 \n, 以 \0 結尾)
char* fgets(char*, int, FILE*); int fputs(const char*, FILE*);
// 格式化
int fscanf(FILE*, const char*, ...); int fprintf(FILE*, const char*, ...);
// 區塊 (二進位)
size_t fread(void* ptr, size_t size, size_t nmemb, FILE*);
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE*);

25. 隨機存取

rewind(fp);           // 回到開頭
fseek(fp, offset, SEEK_SET/CUR/END);  // 移動位置
long ftell(fp);       // 取得目前位置 (相對開頭)
int feof(FILE*);      // 檢查 EOF 標記 (讀取失敗後才置位)

十、動態記憶體管理

26. malloc/free 基礎

void *malloc(size_t size);  // 成功回傳對齊位址,失敗回傳 NULL
void free(void *ptr);       // ptr 必須是 malloc/calloc/realloc 回傳值
// 必須配對,釋放後指標不可再用 (懸空指標),建議 free 後設 NULL

27. 常見錯誤

  • 未檢查 NULL 直接解參考
  • 釋放非堆疊記憶體、重複釋放、釋放後使用
  • realloc(ptr, 0) 行為實作定義 (可能等同 free),C17 標準化為類似 free

十一、預處理指令

28. #include 路徑搜尋差異

  • #include <header.h>:僅搜尋系統標準路徑 (/usr/include, 專案 include 目錄)
  • #include "header.h":先搜尋當前檔案目錄,找不到再搜尋系統路徑

29. 條件編譯常用模式

#ifdef DEBUG
    #define LOG(...) printf(__VA_ARGS__)
#else
    #define LOG(...)
#endif

#ifndef HEADER_H
#define HEADER_H
// 內容
#endif

總結

C 語言的精髓在於「理解機器模型」:記憶體佈局、指標運算、呼叫慣例、預處理機制。掌握這 29 點核心知識,並養成 檢查回傳值、初始化變數、配對 malloc/free、邊界檢查、避免未定義行為 的習慣,即能寫出健壯、高效、可移植的 C 程式碼。

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