本文實現一個極簡版 printf,支持 %d(十進制整數)、%x(十六進制)、%s(字符串)、%c(字符)四種格式。通過遞歸輸出數字、查表轉十六進制、直接輸出字符/字符串,展示格式化輸出的核心邏輯。
print_Dec遞歸分解:先輸出高位,再輸出低位。
static void print_Dec(uint32_t n) {
if (n >= 10) {
print_Dec(n / 10);
n %= 10;
}
putchar((char)(n + '0'));
}
print_Hex固定 32 位,每 4 位輸出一個十六進制字符,高位補 0。
static void print_Hex(unsigned int hex) {
int i = 8;
putchar('0'); putchar('x');
while (i--) {
unsigned char c = (hex & 0xF0000000) >> 28;
putchar(c < 0xA ? c + '0' : c - 0xA + 'a');
hex <<= 4;
}
}
print_String遍歷字符直到 \0。
void print_String(const char *s) {
while (*s) putchar(*s++);
}
print_char直接 putchar。
void print_char(char ch) { putchar(ch); }
#include <stdio.h>
#define myfflush(out) do {} while (0)
typedef unsigned int uint32_t;
static void print_Dec(uint32_t n) {
if (n >= 10) { print_Dec(n / 10); n %= 10; }
putchar((char)(n + '0'));
}
static void print_Hex(unsigned int hex) {
int i = 8;
putchar('0'); putchar('x');
while (i--) {
unsigned char c = (hex & 0xF0000000) >> 28;
putchar(c < 0xA ? c + '0' : c - 0xA + 'a');
hex <<= 4;
}
}
void print_String(const char *s) { while (*s) putchar(*s++); }
void print_char(char ch) { putchar(ch); }
int main(void) {
print_Dec(10); putchar('\n'); // 輸出 10
print_Hex(0xA); putchar('\n'); // 輸出 0x0000000a
print_String("hello world"); // 輸出 hello world
myfflush(stdout);
return 0;
}
10
0x0000000a
hello world
-、+、0、#、空格)。%p 指針、%u 無符號、%o 八進制、%f 浮點數。vsprintf / vprintf 可變參數版本(參考 Linux 內核 vsprintf.c)。通過遞歸分解整數、位運算提取十六進制位、簡單遍歷輸出字符串/字符,即可構建出基本的格式化輸出功能。這是理解 printf 族函數內部原理的最佳切入點。