Кодирование чисел Variant Си ? Вывод в бинарные файлы

Пытаюсь сделать задание 1 вот отсюда, алгоритм кодирования, декодирования и генерации взят оттуда же. Не могу понять как работает encode_variant. Почему он возращает size_t ? Ну пробовал потыкать на вход даю число 122 допустим, возвращается 1, даю 222, возвращается 2. Как то не очень оно похоже на закодированное число. И следующий вопрос как из этого закодированного числа с помощью decode получить исходное. Не понимаю в каком виде нужно передать число 2, допустим, чтобы его назад декодировать в 222. Задание состоит в генерации двух файлов с 100000000 случайными числами, в одном должны быть числа без кодирования в другом с ним и нужно сравнить размеры файлов, получаю файлы одинакового размера 3907 КБ, по логике вещей после кодирования эти числа должны занимать меньший объем. Вот код

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#define ERROR_FILE_OPEN -3

size_t encode_varint(uint32_t value, uint8_t* buf)
{
    assert(buf != NULL);
    uint8_t* cur = buf;
    while (value >= 0x80) {
        const uint8_t byte = (value & 0x7f) | 0x80;
        *cur = byte;
        value >>= 7;
        ++cur;
    }
    *cur = value;
    ++cur;
    return cur - buf;
}

uint32_t decode_varint(const uint8_t** bufp)
{
    const uint8_t* cur = *bufp;
    uint8_t byte = *cur++;
    uint32_t value = byte & 0x7f;
    size_t shift = 7;
    while (byte >= 0x80) {
        byte = *cur++;
        value += (byte & 0x7f) << shift;
        shift += 7;
    }
    *bufp = cur;
    return value;
}

/*
 * Диапазон             Вероятность
 * -------------------- -----------
 * [0; 128)             90%
 * [128; 16384)         5%
 * [16384; 2097152)     4%
 * [2097152; 268435455) 1%
 */
uint32_t generate_number()
{
    const int r = rand();
    const int p = r % 100;
    if (p < 90) {
        return r % 128;
    }
    if (p < 95) {
        return r % 16384;
    }
    if (p < 99) {
        return r % 2097152;
    }
    return r % 268435455;
}

int main(void){
    uint8_t* mybuffer;
    mybuffer = malloc(sizeof(uint8_t));
    FILE *output1 = NULL;
    FILE *output2 = NULL;
    output1 = fopen("C:/Users/forjo/Documents/C Prog/Programms/bitwise/compressed.dat","wb");
    if (output1 == NULL) {
        printf("Error opening file");
        getch();
        exit(ERROR_FILE_OPEN);
    }
    output2 = fopen("C:/Users/forjo/Documents/C Prog/Programms/bitwise/uncompressed.dat","wb");
    if (output1 == NULL) {
        printf("Error opening file");
        getch();
        exit(ERROR_FILE_OPEN);
    }
    size_t count = 1;
    for (int i=0; i<1000000; i++){
    uint32_t random = generate_number();
    uint32_t compress = encode_varint(random,mybuffer);
    fwrite(&compress, sizeof(compress), count, output1);
    fwrite(&random, sizeof(random), count, output2);
    }
    return 0;
}

Ответы (1 шт):

Автор решения: DmitryK

Ну как бы алгоритм простой. Числа типа uint32_t занимают в памяти 4 байта (32 бита). А реальные числа можно представить в памяти меньшим количеством байт. Например, в общем случае uint числа от 0 до 255 - хватит одного байта для записи. Конкретно в этом алгоритме используется только 7 бит, а 8 бит - служебный. Поэтому 1 байта хватит для записи чисел от 0 до 127.
Вот этот алгоритм в файл output2 записывает каждый раз по 4 байта, а в файл output1 - то количество байт, которого достаточно для отображения числа. Но у Вас много ошибок:

int main(void)
{
//    uint8_t* mybuffer;
//     mybuffer = malloc(sizeof(uint8_t)); // неправильно - буфер должен быть не меньше 4 байт
    uint8_t mybuffer[5];

    size_t count = 1;
    for (int i=0; i<1000000; i++)
    { 
      uint32_t random = generate_number();
      size_t compress = encode_varint( random, mybuffer); // compress - количество байт
      
//       fwrite(&compress, sizeof(compress), count, output1); // неправильно! нужно записывать буфер.
      fwrite(mybuffer, 1, compress, output1); // записывается compress значений по 1 байту  
      fwrite(&random, sizeof(random), 1, output2); // записывается 1 значение размером sizeof(uint32_t) байт
    }
    return 0;
}
→ Ссылка