Как вы подходите к созданию полного нового типа данных на «битовом уровне»? - PullRequest
1 голос
/ 07 января 2020

Я хотел бы создать новый тип данных в Rust на «битовом уровне».

Например, с плавающей запятой четвертой точности. Я мог бы создать структуру, которая имеет два числа с плавающей запятой двойной точности и произвольно увеличить точность, разделив квад на два двойных числа, но я не хочу этого делать (это то, что я имею в виду на «уровне битов»).

Я думал об использовании массива u8 или bool, но в обоих случаях я трачу 7 бит памяти (так как bool - это большой байт). Я знаю, что есть несколько ящиков , которые реализуют что-то вроде битовых массивов или битовых векторов, но просмотр их исходного кода не помог мне понять их реализацию.

Как мне создать такой битовый массив, не тратя впустую память, и я бы хотел выбрать этот способ при реализации чего-то вроде типа с четверной точностью?

Я не знаю, как реализовать новые типы данных, которые не используйте типы basi c или структуры, объединяющие типы basi c, и я пока не смог найти решение для inte rnet; возможно я не ищу с правильными ключевыми словами.

1 Ответ

2 голосов
/ 07 января 2020

На ваш вопрос нет прямого ответа: как и любой другой язык программирования, Rust имеет базовый набор правил c для макетов типов. Это связано с тем, что (большинство) реальных процессоров не могут адресовать отдельные биты, требуют определенных выравниваний при обращении к памяти, имеют правила относительно того, как работает арифметика указателей c и c. et c.

Например, если вы создаете тип только из двух битов, вам все равно понадобится 8-битный байт для представления этого типа, потому что просто нет способа обратиться к двум отдельным битам на большинстве операционных кодов процессора; также нет способа получить адрес такого типа, потому что адресация работает, по крайней мере, на уровне байтов. Более полезную информацию об этом можно найти здесь , раздел 2, The Anatomy of a Type. Имейте в виду, что не теряющий битовый тип, о котором вы думаете, должен соответствовать всем упомянутым там правилам.

Это совершенно разумный подход, чтобы представлять то, что вы хотите сделать, например, как один, в виде обертки u128 и реализовать все арифметические c поверх этого типа. Другой, более общий c подход - использовать Vec<u8>. Вы всегда будете делать относительно большое количество бит-маскировок, косвенных и т. Д.

Посмотрите на rust_decimal или подобные ящики, также может быть хорошей идеей.

...