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

Linux 內核風格:C 語言可變參數實現 printf 與 sprintf 完整源碼解析

     編輯:關於C語言

設計目標

不依賴 stdio.h,從零實現 printf/sprintf 核心格式化邏輯,支援 %d %u %x %X %o %c %s %p %n %%、寬度、精度、標誌(- + 0 # space)、長度修飾符(h l L)。

核心組件

1. 數字轉字符串 number()

  • 處理進制(2-36)、符號、填充、對齊、前綴(0x)、大小寫。
  • 使用 __do_div 宏模擬 64 位除法(內核兼容 32 位架構)。
  • 結果逆序存入臨時緩衝區 tmp[66],再按格式寫入目標緩衝區。

2. 核心格式化 vsprintf()

  • 解析格式字符串 fmt,提取標誌、寬度、精度、長度、類型。
  • 從 va_list 取參,按類型調用 number() 或直接寫字符/字符串。
  • 返回寫入字符數。

3. 封裝接口

int sprintf(char *buf, const char *fmt, ...) {
    va_list args; va_start(args, fmt);
    int i = vsprintf(buf, fmt, args);
    va_end(args); return i;
}
int printf(const char *fmt, ...) {
    char buf[1024];
    va_list args; va_start(args, fmt);
    int printed = vsprintf(buf, fmt, args);
    va_end(args);
    puts(buf); // 內核用 console_write,用戶態用 puts/fwrite
    return printed;
}

關鍵源碼片段(節選)

// 標誌位
#define ZEROPAD 1; #define SIGN 2; #define PLUS 4; #define SPACE 8;
#define LEFT 16; #define SMALL 32; #define SPECIAL 64;

// 解析循環
for (str = buf; *fmt; ++fmt) {
    if (*fmt != '%') { *str++ = *fmt; continue; }
    flags = 0; repeat: ++fmt;
    switch (*fmt) { case '-': flags|=LEFT; goto repeat; ... }
    // 寬度、精度、* 動態取參
    // 長度修飾符 h/l/L
    // 類型分發: c/s/p/n/%/o/x/X/d/i/u
    // 取參: va_arg(args, type)
    // 調用 number() 或直接寫入
}
*str = '\0'; return str - buf;

運行測試

int main() {
    myprintf("輸出字符串:hello world!\n");
    myprintf("sum(十進制):%d\n", 7);
    myprintf("sum(16進制):%p\n", 7);
    char buffer[128];
    mysprintf(buffer, "輸出字符串:hello world!\n");
    myprintf("buffer:%s\n", buffer);
    return 0;
}

輸出:

輸出字符串:hello world!
sum(十進制):7
sum(16進制):0x00000007
輸出字符串:hello world!
buffer:輸出字符串:hello world!

工程價值

  • 內核/裸機/引導加載器環境無標準庫時可直接移植。
  • 源碼可讀性強,便於裁剪(如僅保留 %d %s %x 減小體積)。
  • 理解格式化解析狀態機,有助於調試、安全審計(格式化字符串漏洞)。

總結

Linux 內核 vsprintf.c 是 C 語言可變參數格式化輸出的教科書級實現。通過標誌位狀態機解析格式串、統一數字轉換函數 number()、va_list 參數提取,實現了功能完整、可移植、無標準庫依賴的 printf/sprintf 族函數。

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