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

C 語言 18 個經典問題深度解析與最佳實踐

     編輯:關於C

前言

C 語言雖歷久彌新,但其細節陷阱常讓開發者踩坑。本文精選 18 個經典問題,涵蓋指標運算、記憶體管理、字串處理、編譯器行為等核心主題,並給出標準解答與實務建議,助你建立扎實的 C 語言功力。

問題與解析

1. 靜態變數初始化不可使用函式呼叫

char *p = malloc(10); // 編譯錯誤:初始化器非常數

解析:靜態/全域變數的地址必須在編譯期確定,malloc 在執行期分配記憶體,故非法。建議:改用巨集定義大小,或在函式內部(自動變數)初始化。

2. *p++ 運算子優先序

*p++ 等價 *(p++):先取值再遞增指標。若要遞增指向的值,寫 (*p)++ 或 ++*p。建議:善用括號消除歧義,提升可讀性。

3. 型別轉換後無法直接遞增指標

((int *)p)++; // 錯誤:轉換結果為右值,不可遞增

正確做法:p = (char *)((int *)p + 1); 或 p += sizeof(int);。GCC 會依指標型別自動調整位移。

4. 空指標 vs 未初始化指標

空指標(NULL)保證不指向任何物件;未初始化指標值不定,可能指向任意位址。鐵律:宣告指標即初始化為 NULL。

5. 整數 0 表示空指標的語境限制

在指標語境(初始化、指派、比較、有原型的固定參數函式呼叫)中,0 自動轉為空指標。但變參函式或無原型函式呼叫時,必須強制轉型:(char *)0。建議:統一使用 NULL(Linux 定義為 (void *)0)。

6. 陣列名 arr vs &arr

  • arr:退化為指向第一個元素的指標(T *)。
  • &arr:指向整個陣列的指標(T (*)[N]),sizeof(&arr) == sizeof(arr),但 &arr + 1 跳過整個陣列。

7. 陣列指標的宣告與用途

真正的陣列指標:int (*ap)[N];。通常只需指向元素的指標(int *p = arr;),除非操作「陣列的陣列」。

8. 二維陣列傳遞給函式

二維陣列退化為「陣列指標」而非「指標的指標」。函式簽名應為 void f(int a[][NCOLS]) 或 void f(int (*ap)[NCOLS]),第二維度不可省略。

9. strcat 緩衝區溢位風險

char *s1 = "Hello, ";  // 指向唯讀區,且空間不足
char *s2 = "world!";
strcat(s1, s2);        // 未定義行為

正確: char s1[20] = "Hello, "; 確保目的緩衝區可寫且足夠大。

10. 函式回傳字串/集合的正確方式

回傳指標必須指向:靜態緩衝區、呼叫者提供的緩衝區、或 malloc 分配的記憶體。絕不可回傳區域自動陣列的位址(函式返回後記憶體失效)。

11. free 後作業系統記憶體佔用未下降

大多數 malloc/free 實作(如 glibc ptmalloc)將釋放的記憶體保留於進程堆中供後續複用,不立即歸還 OS。

12. calloc vs malloc

calloc(m,n) 相當於 malloc(m*n) + memset(0)。零填充不保證產生有效空指標或浮點數 0.0。free 可安全釋放 calloc 記憶體。

13. sizeof('a') 在 C 與 C++ 差異

C 語言字元常數型別為 int,故 sizeof('a') == sizeof(int)(通常 4)。C++ 中為 char(1 位元組)。

14. extern int f(struct x *p); 的作用域陷阱

原型中首次出現的結構標籤作用域僅限該原型。解決:在原型前加 struct x; 前向宣告,建立檔案作用域的不完整型別。

15. const int n = 5; int a[n]; 非法

C 語言 const 僅表「唯讀」,非編譯期常數。陣列維度需編譯期常數,請用 #define 或 enum。

16. main 必須回傳 int

標準規定 int main(void) 或 int main(int argc, char *argv[])。void main() 不合規,雖 GCC 允許但不可攜。

17. #pragma 指令

提供編譯器專屬擴展(原始碼列控制、結構對齊、警告抑制等),不可攜但實用。

18. #pragma once

非標準擴展,等同 #ifndef 保護,但可攜性較差。常見參數:message, pack, warning, region 等。

總結

深入理解這 18 個問題,能有效避開 C 語言常見陷阱,寫出更健壯、可攜的程式碼。建議配合編譯器警告(-Wall -Wextra -pedantic)與靜態分析工具持續改善程式品質。

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