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

如何在xv6操作系统中打印long long类型整数?

在xv6中打印long long类型整数的解决方案

xv6自带的printf是极简实现,仅支持%d、%x、%s等基础格式符,没有对long long对应的ll修饰符做适配,所以直接用%llu/%lld会失效。以下是两种可行的解决办法:

方案一:手动实现long long转字符串函数

自己编写转换函数将long long/unsigned long long转为字符串,再通过printf("%s")打印。以下是可直接复用的实现:

无符号long long转字符串(ulltoa)

#include <stdint.h>

void ulltoa(uint64_t num, char *buf, int base) {
    char *ptr = buf, *ptr1 = buf, tmp_char;
    uint64_t tmp_num;

    // 生成逆序的数字字符
    do {
        tmp_num = num;
        num /= base;
        *ptr++ = "0123456789abcdef"[tmp_num - num * base];
    } while (num != 0);

    // 添加字符串结束符
    *ptr = '\0';

    // 反转字符串得到正确顺序
    while (ptr1 < --ptr) {
        tmp_char = *ptr1;
        *ptr1++ = *ptr;
        *ptr = tmp_char;
    }
}

有符号long long转字符串(lltoa)

基于上面的ulltoa处理负数情况:

void lltoa(int64_t num, char *buf, int base) {
    char *ptr = buf;
    uint64_t unum;

    // 十进制负数添加负号
    if (base == 10 && num < 0) {
        *ptr++ = '-';
        unum = (uint64_t)-num;
    } else {
        unum = (uint64_t)num;
    }
    ulltoa(unum, ptr, base);
}

使用示例

#include "types.h"
#include "stdio.h"

// 上面的ulltoa和lltoa函数放在此处

int main() {
    long long signed_num = -123456789012345LL;
    unsigned long long unsigned_num = 987654321098765ULL;
    char buf[64];

    // 打印有符号long long
    lltoa(signed_num, buf, 10);
    printf("Signed long long: %s\n", buf);

    // 打印无符号long long
    ulltoa(unsigned_num, buf, 10);
    printf("Unsigned long long: %s\n", buf);

    // 十六进制打印
    ulltoa(unsigned_num, buf, 16);
    printf("Hex unsigned long long: 0x%s\n", buf);

    return 0;
}

方案二:修改xv6的printf源码,添加ll修饰符支持

直接修改xv6自带的printf.c,让原生printf支持%lld和%llu:

  1. 打开xv6源码目录下的printf.c,修改printnum函数的参数类型为uint64_t(兼容unsigned long long):
static int printnum(uint64_t num, int base, int sign) {
    char buf[32];
    char *ptr = buf + sizeof(buf);
    int len = 0;

    if(num == 0){
        *--ptr = '0';
    } else {
        while(num > 0){
            *--ptr = "0123456789abcdef"[num % base];
            num /= base;
        }
    }
    if(sign){
        *--ptr = '-';
    }
    while(ptr < buf + sizeof(buf)){
        len += putchar(*ptr++);
    }
    return len;
}
  1. 在printf函数中添加ll修饰符的解析逻辑,并适配long long类型参数:
int printf(const char *fmt, ...) {
    va_list ap;
    int len = 0;
    uint64_t uv;
    int64_t v;
    char *s;

    va_start(ap, fmt);
    while(*fmt){
        if(*fmt != '%'){
            len += putchar(*fmt++);
            continue;
        }
        fmt++;

        // 解析ll修饰符
        int is_longlong = 0;
        if(*fmt == 'l'){
            fmt++;
            if(*fmt == 'l'){
                is_longlong = 1;
                fmt++;
            }
        }

        switch(*fmt){
        case 'd':
            if(is_longlong){
                v = va_arg(ap, int64_t);
                if(v < 0){
                    len += putchar('-');
                    uv = -v;
                } else {
                    uv = v;
                }
            } else {
                int iv = va_arg(ap, int);
                if(iv < 0){
                    len += putchar('-');
                    uv = -iv;
                } else {
                    uv = iv;
                }
            }
            len += printnum(uv, 10, 0);
            break;
        case 'u':
            if(is_longlong){
                uv = va_arg(ap, uint64_t);
            } else {
                uv = va_arg(ap, unsigned int);
            }
            len += printnum(uv, 10, 0);
            break;
        case 'x':
            if(is_longlong){
                uv = va_arg(ap, uint64_t);
            } else {
                uv = va_arg(ap, unsigned int);
            }
            len += printnum(uv, 16, 0);
            break;
        case 's':
            s = va_arg(ap, char*);
            while(*s){
                len += putchar(*s++);
            }
            break;
        case 'c':
            len += putchar(va_arg(ap, int));
            break;
        case '%':
            len += putchar('%');
            break;
        default:
            len += putchar('%');
            len += putchar(*fmt);
            break;
        }
        fmt++;
    }
    va_end(ap);
    return len;
}
  1. 修改完成后重新编译xv6:
make clean && make
  1. 之后即可直接使用%lld和%llu打印long long类型:
long long test_signed = -987654321012345LL;
unsigned long long test_unsigned = 123456789012345ULL;
printf("Signed: %lld\nUnsigned: %llu\nHex: %llx\n", test_signed, test_unsigned, test_unsigned);

内容的提问来源于stack exchange,提问作者YH J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:53:34