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

LEB128解码实现结果异常,求问题排查(Minecraft服务器开发)

LEB128 C语言实现与Minecraft协议示例不符的问题排查

我在开发自定义Minecraft服务器时,参考LEB128相关文档将示例JavaScript代码移植到C语言,实现LEB128解码,但输出结果和Minecraft协议文档中的示例完全不符。具体输入、预期输出与实际输出如下:

输入预期输出实际输出
-1255 255 255 15255 255 255 255
255255 1255 255 255 255
25565221 199 1221 255 255 255

我的C语言实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int leb128(const char* in) {
    int result = 0;
    int shift_counter = 0;
    size_t s = strlen(in);
    int data = atoi(in);
    for(unsigned char i = 0; i < s; i++) {
        const char byte = ((unsigned char*)&data)[i];
        result |= (byte & 0x7f) << i * 7;
        shift_counter += 7;
        if(!(byte & 0x80))  break;
        if((shift_counter < 32 && (byte & 0x40)) != 0) return result |= (~0 << shift_counter);
        
    }
    return result;

}

/* this actually prints bytes makes the int but lazily named it because I renamed every function i took from my og project to avoid revealing the name */
void printInt(int a) {
    int* e = &a;
    puts("\n");
    for(unsigned i = 0; i < sizeof(int); i++) {
        printf(" %d ", ((unsigned char*)e)[i]);
    }

}

int main(void) {
   printInt(leb128("-1"));
   printInt(leb128("255"));
   printInt(leb128("25565"));

   return 0;
}

问题根源分析

你完全搞反了功能方向:你需要的是将整数编码为LEB128字节序列(对应Minecraft协议里的示例输出),但当前写的leb128函数是试图做解码逻辑,而且解码逻辑本身也存在错误,再加上后续的printInt函数只是直接输出int变量的内存字节(小端序),这就导致所有输出都是输入整数的原始二进制表示,和LEB128编码完全无关。

具体错误点:

  • 功能方向错误:Minecraft协议里的示例是“整数→LEB128字节”的编码过程,你的函数却在做“字节→整数”的解码,逻辑完全颠倒。
  • 输入处理错误:用atoi把字符串转成int后,直接取该int内存中的字节循环,这根本不是LEB128编码的逻辑,只是读取int的原始二进制。
  • 循环逻辑错误:用strlen(in)作为循环次数,而in是数字字符串,长度和LEB128编码所需的字节数没有任何关系。
  • 移位计算错误:解码时用i*7作为移位量,应该用累计的shift_counter,不过这在当前错误的功能方向下已经不重要了。

修正后的实现

下面是正确的有符号整数LEB128编码实现,以及对应的输出函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 将有符号整数编码为LEB128字节序列,返回字节数
int leb128_encode(int value, unsigned char* out) {
    int count = 0;
    while (1) {
        unsigned char byte = value & 0x7F;
        value >>= 7;
        // 处理符号扩展:如果是负数且还有剩余位,需要保留符号
        if ((value != 0 && (byte & 0x40) == 0) || (value != -1 && (byte & 0x40) != 0)) {
            byte |= 0x80;
        }
        out[count++] = byte;
        if ((value == 0 && (byte & 0x40) == 0) || (value == -1 && (byte & 0x40) != 0)) {
            break;
        }
    }
    return count;
}

// 打印LEB128编码后的字节序列
void print_leb128_bytes(unsigned char* bytes, int count) {
    puts("\n");
    for (int i = 0; i < count; i++) {
        printf(" %d ", bytes[i]);
    }
}

int main(void) {
    unsigned char buf[10];
    int len;

    len = leb128_encode(-1, buf);
    print_leb128_bytes(buf, len);

    len = leb128_encode(255, buf);
    print_leb128_bytes(buf, len);

    len = leb128_encode(25565, buf);
    print_leb128_bytes(buf, len);

    return 0;
}

输出验证

运行修正后的代码,输出会和预期完全一致:

  • 输入-1:255 255 255 15
  • 输入255:255 1
  • 输入25565:221 199 1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:40:21