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

Windows Native 開發核心筆記:C 語言函數完整指南(聲明、定義、遞迴、可變參數、儲存類別)

     編輯:關於C語言

Windows Native 開發核心筆記:C 語言函數完整指南

在 Windows Native 開發(驅動程式、系統服務、核心模組)中,C 語言函數機制是基石。本文系統整理函數聲明/定義規範、參數傳遞機制、遞迴實作、變數儲存類別與可變參數處理,並針對內核開發常見陷阱給出最佳實踐。

函數聲明與定義規範

頭檔中聲明

// cFunction.h
#ifndef _MYHEAD_FUNCTION_
#define _MYHEAD_FUNCTION_

#ifdef __cplusplus
extern "C"  // 防止 C++ 名稱修飾,確保 C 連結語意
#endif

// 標準聲明:供外部模組調用
char *demo_cFunction(void);
long recursion(int n);
void update(int ary[], int aryLength);

// 函數原型:僅保留型別,參數名可省略
void update(int[], int);

// 內部函數:static 限制連結可見性於本編譯單元
static void cFunction_demo1(void);

// 外部函數:extern 明確標示(預設即為 extern)
extern void cFunction_demo2(void);
void cFunction_demo3(void);  // 隱含 extern

#endif

原始檔中定義

// cFunction.c
#include "pch.h"
#include "cFunction.h"
#include "cHelper.h"

// 全域變數:靜態儲存期,整個程式存續期
int global01 = 100;

// 本檔案內部函數:無需外部聲明即可調用
void function0(void) { }

// 函數定義
char *demo_cFunction(void) {
    function0();  // 同檔案前向調用無需聲明
    // ... 實作細節
}

參數傳遞:值傳遞與陣列退化

C 語言**僅支援值傳遞**。形參是實參的副本,生命週期僅限函數執行期間。

int function2(int a, int b) {  // a, b 為形參
    return a + b;
}

// 調用端
int x = function2(1, 2);  // 1, 2 為實參

陣列參數實為指標

void update(int ary[], int len) {  // 等價於 int *ary
    for (int i = 0; i < len; i++) ary[i] = 0;  // 修改影響原陣列
}

// 調用
int arr[] = {0,1,2,3,4};
update(arr, 5);  // arr 退化為指標,實際傳遞首元素位址

注意:陣列長度資訊**不會**傳遞給函數,必須額外傳遞 len 參數。

遞迴函數實作

// 計算 1+2+...+n
long recursion(int n) {
    long result = 0;
    if (n > 0) {
        result += n;
        result += recursion(n - 1);  // 遞迴呼叫
    }
    return result;
}

內核開發中**慎用遞迴**:棧空間有限(通常 12KB~24KB),深度遞迴易導致棧溢位。優先考慮迴圈改寫或尾遞迴優化(需編譯器支援)。

變數儲存類別與作用域

關鍵字儲存期作用域初始值典型用途
(無)/auto動態(棧)區塊不定區域變數
static靜態區塊/檔案0保持狀態、檔案內部函數
register動態(暫存器/棧)區塊不定熱點迴圈計數器(建議由編譯器決定)
volatile動態/靜態依宣告位置不定硬體暫存器、訊號處理、多執行緒共享變數
extern靜態全域0跨檔案共享全域變數/函數

關鍵範例

void demo_variable2(void) {
    int i = 0;              // auto,動態儲存
    static int j = 0;       // 靜態區域變數,跨呼叫保持值
    register int x = 0;     // 建議放入暫存器,不可取址 &
    volatile int y = 0;     // 強制記憶體存取,防編譯器優化

    extern int global02;    // 引用他處定義的全域變數
    extern int global03;
    int p02 = global02;     // 使用外部變數
}
int global02 = 200, global03 = 300;  // 定義點在使用點之後

可變參數函數

使用 <stdarg.h> 機制:

#include <stdarg.h>

float average(int count, ...) {
    va_list ap;
    va_start(ap, count);           // 初始化,count 為最後一個固定參數
    long sum = 0;
    for (int i = 0; i < count; i++)
        sum += va_arg(ap, int);    // 依序取出參數,需指定型別
    va_end(ap);                    // 清理
    return (float)sum / count;
}

// 調用
float avg = average(4, 1, 2, 3, 4);  // 2.5

內核開發注意:va_list 在 x64 呼叫慣例中為結構體,傳遞時需傳指標或使用 va_copy;嚴禁在中斷上下文(IRQL > PASSIVE_LEVEL)使用浮點/可變參數。

內核開發最佳實踐清單

  • ✅ 所有對外 API 加 extern "C" 防名稱修飾
  • ✅ 內部函數加 static 減少符號汙染
  • ✅ 陣列參數**必須**配合長度參數,或使用 _In_reads_(len) SAL 註解
  • ✅ 避免遞迴,改用迴圈或工作項佇列
  • ✅ 共享變數加 volatile 或使用互斥體/自旋鎖
  • ✅ 可變參數函數僅用於 PASSIVE_LEVEL 除錯輸出
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved