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

經典 C 語言面試題精選與詳細解析

     編輯:關於C語言

volatile 關鍵字

作用:告訴編譯器該變數可能隨時被外部改變(如中斷、硬體暠存器、多執行緒共享旗標),禁止優化,每次存取必須從記憶體讀寫。

適用場景:

  1. 中斷服務程式修改、供其他程式檢測的變數
  2. 多任務環境下任務間共享的標志變數
  3. 記憶體映射的硬體暠存器

TCP/IP 協議分層

應用層:SMTP、FTP、Telnet 等應用程式協議。
傳輸層:TCP(可靠、流控、擁塞控制,表頭 20+ 位元組)、UDP(不可靠、無連線、表頭 8 位元組、低延遲)。
網路層:IP、ICMP、ARP、RARP。
資料鏈路層:Ethernet、PPP。
物理層:光纖、雙絞線等傳輸媒介。

預處理與編譯

預處理(預編譯)處理 # 開頭指令:檔案包含(#include)、巨集替換(#define)、條件編譯(#if/#ifdef)。輸出為無巨集、無註解的純 C 代碼,再交由編譯器編譯。

C 與 C++ struct 差異

  • C 的 struct 僅能包含資料成員,不可含成員函式。
  • C++ 的 struct 可含成員函式、建構子、解構子,預設存取權限為 public;class 預設為 private。

絕對地址函式呼叫

將絕對地址強轉為函式指標並呼叫:

typedef void (*voidFuncPtr)();
*((voidFuncPtr)0x100000)();
// 或
*((void (*)())0x100000)();

常用於嵌入式系統呼叫固定地址的 Bootloader 或中斷向量。

進程與執行緒

  • 進程是資源集合(記憶體、檔案描述符等),本身不執行代碼。
  • 執行緒是 CPU 排程基本單位,擁有獨立堆疊,共享進程資源。
  • 程式啟動時 OS 自動建立主執行緒。

記憶體管理陷阱:free 後再使用

void GetMemory(char **p, int num) { *p = (char*)malloc(num); }
int main() {
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello");
    free(str);          // 釋放記憶體
    if (str != NULL)    // 錯誤:str 指標值未變,仍指向已釋放區塊
        strcpy(str, "world"); // 未定義行為
    printf("%s", str);
}

正確做法:free(str); str = NULL; 避免野指標。

整數溢位與長整型常數

16 位機上 60*60*24*365 會溢位,需加 L 或 UL 強制長整型運算:

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

硬體暠存器存取

利用巨集將絕對地址映射為 volatile 指標:

#define rWTCON (*(volatile unsigned *)0x53000000)

無號與有號比較陷阱


unsigned int a = 6;
int b = -20;
(a + b > 6) ? puts("> 6") : puts("<= 6"); // a+b 經整數提升為 unsigned,結果極大,輸出 "> 6"

浮點數比較

避免 x == 0.0,改用誤差範圍:

#define EPSINON 1e-9
if ((x >= -EPSINON) && (x <= EPSINON)) // 視為零

assert 斷言

#include <assert.h> void assert(int expression); 僅在 Debug 建置生效,Release 時被移除。

函式傳回區域陣列錯誤


char *GetMemory() {
    char p[] = "hello world"; // 區域陣列,棧上分配
    return p; // 錯誤:函式結束後記憶體失效
}

正確做法:動態分配 malloc、靜態陣列、或呼叫端提供緩衝區。

計算整數二進位中 1 的個數

Brian Kernighan 演算法(每次清除最低位 1):


int countBits(unsigned int n) {
    int c = 0;
    for (; n; ++c) n &= (n - 1);
    return c;
}

查表法(256 字節預計算表,適合 32/64 位整數):


unsigned char BitsSetTable256[256];
void initTable() {
    for (int i = 0; i < 256; ++i)
        BitsSetTable256[i] = (i & 1) + BitsSetTable256[i / 2];
}
int countBitsFast(unsigned int n) {
    unsigned char *p = (unsigned char*)&n;
    return BitsSetTable256[p[0]] + BitsSetTable256[p[1]] +
           BitsSetTable256[p[2]] + BitsSetTable256[p[3]];
}

typedef vs #define

特性typedef#define
處理階段編譯期預處理期
型別檢查有無(純文字替換)
作用域有(遵循區塊作用域)無(全域,直到 #undef)
用途型別別名巨集常數、程式碼片段
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved