Для целых чисел простой метод, который я нашел часто полезным, - это кодирование BER.В основном для целого числа без знака вы пишете 7 битов для каждого байта, используя 8-й бит, чтобы отметить, требуется ли еще один байт
void berPack(unsigned x, std::vector<unsigned char>& out)
{
while (x >= 128)
{
out.push_back(128 + (x & 127)); // write 7 bits, 8th=1 -> more needed
x >>= 7;
}
out.push_back(x); // Write last bits (8th=0 -> this ends the number)
}
для целого числа со знаком, вы кодируете знак в младшем значащем бите и используетета же кодировка, что и раньше
void berPack(int x, std::vector<unsigned char>& out)
{
if (x < 0) berPack((unsigned(-x) << 1) + 1, out);
else berPack((unsigned(x) << 1), out);
}
При таком подходе небольшие числа будут занимать меньше места.Другое преимущество состоит в том, что это кодирование уже не зависит от архитектуры (т. Е. Данные будут правильно пониматься независимо от порядкового номера системы) и что один и тот же формат может обрабатывать различные целочисленные размеры, и вы можете отправлять данные из 32-битной системы в64-битная система без проблем (при условии, конечно, что сами значения не переполняются).
Цена, которую нужно заплатить, это, например, значения без знака от 268435456 (1 << 28) до 4294967295 ((1 << 32)) - 1) потребуется 5 байтов вместо 4 байтов стандартной фиксированной 4-байтовой упаковки. </p>