Это сильно зависит от используемой архитектуры, ОС и компилятора, но если вы знаете эти вещи, вы можете что-то с этим делать.
x86_64 определяет 48-битный 1 байтовое виртуальное адресное пространство в аппаратном обеспечении, что означает, что практически все операционные системы и компиляторы будут его использовать. Это означает:
- верхние 17 бит всех действительных адресов должны быть одинаковыми (все нули или все единицы)
- нижние k биты любого 2 k адреса, выровненного по байтам, должны быть все 0s
- вдобавок, почти все операционные системы (Windows, Linux и OSX по крайней мере ) зарезервировать адреса с старшими битами, установленными как адреса ядра - все адреса пользователей должны иметь старшие 17 битов все 0
Таким образом, это дает вам множество способов упаковки действительного указателя в меньшее, чем 64 бита, а затем реконструкция исходного указателя с помощью инструкций сдвига и / или маски.
Если вам нужно только 3 бита и всегда использовать 8-байтовые выровненные указатели, вы можете использовать нижние 3 бита для кодирования дополнительной информации , и замаскируйте их перед использованием указателя.
Если вам нужно больше бит, вы можете сдвинуть указатель вверх (влево) на 16 бит и использовать эти младшие 16 бит для информации. Чтобы восстановить указатель, просто сдвиньте вправо на 16.
Чтобы выполнять операции сдвига и маскирования для указателей, вам необходимо преобразовать их в intptr_t
или int64_t
(они будут одного типа на любых 64- битовая реализация C или C ++)
1 Есть некоторые намеки на то, что вскоре может появиться оборудование, которое расширяет это до 56 бит, поэтому только верхние 9 бит должно быть 0 или 1, но пройдет некоторое время, прежде чем какая-либо ОС будет поддерживать это