You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用stdarg.h实现C语言简易printf函数的错误修复

修复手动实现可变参数printf的问题

核心错误分析

你的代码读取可变参数时出现垃圾值,根源有两个:

  1. 指针步长错误:用void**遍历参数时,每次arg++会跳过一个指针大小(64位系统下是8字节),但int类型仅占4字节,导致读取位置偏移,拿到的是栈上的垃圾数据。
  2. 整数溢出未处理:print_int中当输入为INT_MIN(int类型的最小值)时,n = -n会触发溢出,属于未定义行为。

修复后的完整代码

#include <stdio.h>
#include <limits.h> // 用于INT_MIN定义

void print_uint(unsigned int n) {
    if (n / 10)
        print_uint(n / 10);
    putchar(n % 10 + '0');
}

void print_int(int n) {
    if (n < 0) {
        putchar('-');
        // 转换为unsigned int处理INT_MIN,避免溢出
        print_uint((unsigned int)-n);
        return;
    }
    print_uint((unsigned int)n);
}

void print_string(char *s) {
    while (*s)
        putchar(*s++);
}

void my_printf(char *format, ...) {
    // 用char*跟踪参数位置,初始指向format参数后的第一个可变参数
    char *arg = (char*)&format + sizeof(format);

    for (char *p = format; *p; p++) {
        if (*p != '%') {
            putchar(*p);
            continue;
        }

        switch (*++p) {
            case 'd': {
                int val = *(int*)arg;
                print_int(val);
                arg += sizeof(int);
                break;
            }
            case 'u': {
                unsigned int val = *(unsigned int*)arg;
                print_uint(val);
                arg += sizeof(unsigned int);
                break;
            }
            case 's': {
                char *val = *(char**)arg;
                print_string(val);
                arg += sizeof(char*);
                break;
            }
            case '%':
                putchar('%');
                break;
            default:
                putchar(*p);
                break;
        }
    }
}

int main() {
    int x = 42;
    unsigned int y = 1234567890;
    char *s = "Hello, world!";
    int min_int = INT_MIN; // 测试INT_MIN情况

    my_printf("Testing my_printf:\n");
    my_printf("Signed integer: %d\n", x);
    my_printf("Unsigned integer: %u\n", y);
    my_printf("String: %s\n", s);
    my_printf("Percent sign: %%\n");
    my_printf("INT_MIN: %d\n", min_int); // 新增测试

    return 0;
}

关键修复点说明

  • 参数指针调整:改用char*作为参数跟踪指针,每次根据当前参数的实际大小(sizeof(int)/sizeof(unsigned int)/sizeof(char*))移动指针,确保读取位置正确。
  • INT_MIN处理:将负数转换为unsigned int后调用print_uint,避免直接取反导致的溢出问题。

测试输出

修复后运行会得到正确结果:

Testing my_printf:
Signed integer: 42
Unsigned integer: 1234567890
String: Hello, world!
Percent sign: %
INT_MIN: -2147483648

内容的提问来源于stack exchange,提问作者Dremond Williams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:32:51