Можно ли использовать 4-битные, 8-битные, 16-битные или 32-битные указатели на 64-битной машине?

461
Lance Pollard

Я только что сделал грубый расчет для максимального размера беззнакового 64-битного целого числа, которое:

18,446,744,073,709,551,615 q5 q4 t b m t h 

Рассматривая спецификации оборудования AWS на их самых больших компьютерах, мы выясняем 3,904GB, что:

3,904,000,000,000,000,000 bytes 5 q4 t b m t h 

Для меня это означает, что указатели хранятся как 64-битные целые числа . Я новичок в мышлении о памяти и указателях, но просто хотел уточнить это.

Я немного смущен, хотя все еще. Указатель является «язык программирования конструкт». Технически, даже на 64-битной машине, если вы используете менее чем ~ 4 миллиарда целых чисел (максимальный размер 32-битного целого), то мне интересно, почему вы не можете просто указывать 32-битные указатели. Таким образом, указатели будут 32-битными, пока вы не исчерпаете пространство, тогда вы можете начать использовать 64-битные указатели. Тогда это даст вам немного больше места для большего количества объектов.

Все еще в замешательстве, хотя. Указатель содержит местоположение адреса в памяти . Там написано, что «адрес» 64-битный. Так что, если бы у нас были 32-битные указатели, указывающие на 32-битные фрагменты в 64-битной памяти, я не уверен, что это будет выглядеть или означать. Похоже, это означает, что вам придется делать смещения (хотя я не очень хорошо понимаю это).

Интересно, можно ли продемонстрировать в C, Assembly или JavaScript, как будет выглядеть хранение 32-разрядных указателей в 64-разрядном адресном пространстве. Если C обрабатывает это для вас автоматически, то как это делает Assembly.


Я хотел бы знать, как я мог бы использовать большую память, как описано выше, но хранить 32-разрядные указатели, пока не будет достигнут максимум, затем использовать 64-разрядные указатели, и не уверен, как это будет выглядеть точно. Я постараюсь нарисовать диаграмму, объясняющую, как я об этом думаю.

 | The bars and . are like a ruler and mark the bit positions. - Each row under a number (1, 2, 3, ...) means a memory address. ⬚ Means no data in memory address. ⬒ Means data of type 1 in memory address. ■ Means data of type 2 in memory address. ● Means a bit of integer pointer is plugged into memory address slot. ◌ Means no bit of integer pointer is plugged into memory address slot. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |  1. Empty 64-bit memory. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ⬚ ... ... ...  2. 64-bit memory filled with 32-bit pieces of data (type 1 ⬒, type 2 ■). ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ... ... ...  3. 64-bit memory filled with 64-bit pieces of data. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ... ... ...  4. 64-bit memory filled with 4-bit pieces of data. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ... ... ...  5. 64-bit memory filled with 32-bit pieces of data, with second 32-bits accessed by a 32-bit pointer. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒  ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ...  ... ...  6. 64-bit memory filled with 64-bit pieces of data, with second 64-bits accessed by a 64-bit pointer. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ... ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ... ... ...  7. 64-bit memory filled with 4-bit pieces of data, with second piece of data accessed by a pointer. ◌ ◌ ◌ ◌ ● ● ● ● ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ⬒ ⬒ ... ... ...  8. 64-bit memory filled with 8-bit pieces of data, with second piece of data accessed by a pointer. ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ● ● ● ● ● ● ● ● ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒  ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ◌ ... ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ■ ■ ■ ■ ■ ■ ■ ■ ⬒ ⬒ ⬒ ⬒ ⬒ ⬒ ... ... ... 

Я представляю, что целые числа - это ключи к замку (который является адресом памяти). Пустое отверстие для ключа выглядит как 64 in подряд в (1). Полное отверстие для ключа для 64-битного адреса выглядит как 64 ● в строке в (6). Если я дам 64-битному адресному пространству памяти 32-битный ключ, это будет выглядеть так (5). Таким образом, он не будет полностью заполнять отверстие для ключа длиной 64 бита (длиной 64 дюйма), он будет заполнять (в данном случае) вторую половину. И поэтому кажется, что это не соответствует адресу. Но я пытаюсь указать на 32-битные данные прямо во второй половине! Чтобы сопоставить адрес, кажется, вам нужно заполнить ключевые отверстия в полной 64-битной строке, как в (6). Мне интересно, не нарушено ли мое понимание, пожалуйста, дайте мне знать, где я.

В случае, если это неясно, первые цифры 1-4 на диаграмме показывают данные, которые лежат в памяти (где 1 - пустая память). Вторые цифры 5-8 показывают, что мы пытаемся получить доступ к данным с помощью указателя (черные кружки в ряду - это указатель / ключ для блокировки адреса памяти).

Наконец, у меня есть последний вопрос. Интересно, можете ли вы пойти дальше и хранить данные в еще меньших порциях. Например, хранение 4-битных данных, как в (7). Это просто демонстрирует, как работает система указателей и адресов, более подробно. Я не знаю, можно ли указать 4-битный указатель на 4-битный фрагмент памяти. Похоже, что из-за требований к выравниванию вы должны получать как минимум 8 бит за раз. Но это нормально. Я просто хочу убедиться, что есть или нет возможности использовать n-битный указатель для доступа к n-битным данным в 64-битном пространстве памяти.

И если так, то как бы это выглядело, либо в C, либо в Assembly, либо в JavaScript также будет работать.

Я хотел бы знать это, чтобы знать, как вы должны хранить данные в 64-битной памяти, и что вам разрешено делать с указателями, учитывая, что «адреса памяти являются 64-битными». То есть, если я смогу сделать так, memory.get(a32BitPointer)чтобы он возвращал 32 бита данных из 32-разрядного выровненного слота памяти. (Или, что эквивалентно, 4, 8, 16 и т. Д. Бит данных или указатель размера).

1
Хм, вы думаете, что тысяча - это 10⁶ (10 ^ 6), а миллион - 10⁹ (10 ^ 9)? Scott 5 лет назад 1
Ваш номер слишком неправильный. 3 904 ГБ - это [`3 904 000 000 000`] (https://www.google.com/search?q=3904gb+in+bytes&ie=utf-8&oe=utf-8) (только 9 нулей), а не 3 904 000 000 000 000 000. Проще думать в терминах префиксов ISO KMGTE ... вместо htmbt ... как вы написали. Мне потребовалось время, чтобы понять, что означают т и ч, когда они далеки от тысячи и единицы phuclv 5 лет назад 0

2 ответа на вопрос

4
LawrenceC

Указатель указывает содержит абсолютный адрес.

Если вам нужно добавить значение перед использованием указателя, то у вас есть смещение, а не реальный указатель.

В C указатель void может быть указателем на функцию, например, через него можно вызвать функцию. Чтобы это работало, вам нужны все 64 бита, если процессор находится в 64-битном режиме.

Если ваш процессор поддерживает 64 адресных строки (физически он может иметь меньше), то он имеет адресное пространство 2 ^ 64, которое 0x1 0000 0000 0000 0000- от - 0x0000 0000 0000 0000до 0xFFFF FFFF FFFF FFFF.

Если вы хотите, чтобы указатель использовался инструкциями ЦП без дополнительных инструкций ЦП, чтобы выяснить, что вы на самом деле имеете в виду (собственный код ЦП может иметь дело с указателями напрямую), то он должен быть таким же широким, как адресное пространство ЦП.

Смещения медленнее, потому что ЦП должен добавить, чтобы получить адрес, который вы хотите, хотя ЦП имеют собственные инструкции, которые делают это тоже.

Я не супер эксперт по ISA x86-64, но, вероятно, есть инструкции ЦП, которые обрабатывают 32-битные значения как 64-битные значения с первыми 32-битными значениями, равными 0. ЦП все еще должен внутренне «расширять» реальное значение до 64 бит.

В x86 и x86-64 вы, конечно, можете использовать 8, 16, 32 и 64-битные смещения (никакие инструкции CPU x86 / x86 не работают только с 4-битными значениями)

Указатель не «указывает на абсолютный адрес». Значение указателя является абсолютным адресом - местом в памяти. (Хорошо, хорошо. На что указывает указатель, т. Е. На то, что содержится в этой ячейке памяти, _could_ может быть абсолютным адресом, но в равной степени это может быть адрес какого-либо элемента данных или начальный адрес структуры данных и т. Д.) Jamie Hanrahan 5 лет назад 1
1
phuclv

Во-первых, для 3904 ГБ памяти требуется только 42 бита для адресации. Он состоит только из 3 904 000 000 000байтов вместо того, что вы рассчитали

PS C:\> [math]::Log(3904GB, 2) 41.9307373375629 

Технически, даже на 64-битной машине, если вы используете менее чем ~ 4 миллиарда целых чисел (максимальный размер 32-битного целого), то мне интересно, почему вы не можете просто указывать 32-битные указатели. Таким образом, указатели будут 32-битными, пока вы не исчерпаете пространство, тогда вы можете начать использовать 64-битные указатели. Тогда это даст вам немного больше места для большего количества объектов.

x32 ABI - это 64-битный x86 ABI, использующий 32-битные указатели. Процессы имеют только 32-разрядное адресное пространство, что означает, что они не могут использовать более 4 ГБ памяти (это не проблема для большинства пользовательских приложений), но они смогут использовать все большее и большее пространство регистров. Пространство глобальной памяти по-прежнему составляет 64 бита, поскольку оно фиксировано аппаратно, поэтому 32-разрядный указатель будет использоваться в качестве смещения к базовому адресу процесса вместо прямого указателя. Реализация просто так

void* getRealPointer(uintptr_t base_addr, uint32_t ptr) { return (void*)(base_addr + ptr); // value stored in pointer is the offset/distance from base } 

Этот метод также распространен во многих других 64-разрядных архитектурах, таких как Sparc ( почему Linux на архитектуре sparc64 использует 32-разрядные указатели в пользовательском пространстве и 64-разрядные указатели в пространстве ядра? ), MIPS или PowerPC, поскольку на переходном этапе до 64-битных они не увеличили количество регистров, таких как x86 и ARM, что означает, что 32-битный процесс, вероятно, быстрее, чем 64-битный, если ему не требуется 64-битная математика или более 2/3 / 4ГБ баран

На 64-разрядных процессорах, таких как G5, Debian PPC использует 64-разрядное ядро ​​с 32-разрядным пользовательским пространством. Это связано с тем, что 64-разрядные процессоры PowerPC не имеют «32-разрядного режима», как архитектура Intel 64 / AMD64. Следовательно, 64-разрядные программы PowerPC, которым не нужны 64-разрядные математические функции, будут работать несколько медленнее, чем их 32-разрядные аналоги, поскольку 64-разрядные указатели и длинные целые числа занимают вдвое больше памяти, быстрее заполняют кэш ЦП и, следовательно, требуют большего частые обращения к памяти.

https://lwn.net/Articles/395894/

Тем не менее, вы не можете просто использовать 32-битные указатели until you run out of space then start using 64-bit pointers, это не имеет смысла. Тип всегда имеет фиксированный размер. Если вы зарезервируете место только для 32-битного указателя, что произойдет, если вам нужно использовать 64-битные указатели? Где вы будете хранить верхнюю часть?


Поэтому, если бы у нас были 32-разрядные указатели, указывающие на 32-разрядные фрагменты в 64-разрядной памяти, я не уверен, как это будет выглядеть или иметь в виду

Это называется адресной памятью . Вместо того, чтобы указывать на каждый байт, теперь каждое значение просто указывает на другое слово

Будет проще представить, что память состоит из серии линейных ячеек, которые идентифицируются уникальными идентификаторами. Эти идентификаторы - это то, что мы обычно называем «адрес», и то, что хранится в указателях. Размер ячейки обычно составляет 1 байт в современных системах (т. Е. Адресно-байтовая память). Однако многие старые системы, такие как Unisys или PDP, используют адресную память со словом, в котором ячейка содержит слово (в случае этих архитектур 36 бит длиной). Поэтому в этих системах char*будет больше, чем, int*поскольку вам понадобится еще несколько бит для хранения позиции байта, к которому вы хотите обратиться

Я не совсем понимаю вашу диаграмму, но людям редко приходится обращаться с каждым таким битом, так как это, очевидно, уменьшает общий объем памяти, который мы можем адресовать. Хотя, честно говоря, существует несколько архитектур с битовой адресацией памяти, в основном встроенные системы. Если выглядит так, как будто вы хотите получить 32-битное младшее 64-битное значение, когда вы назначаете процессору 32-битный адрес, но это не сработает. Для адресации каждой половины вам понадобится еще один значащий бит вместо половины количества битов, подобных этому. Принцип прост: если мы используем больший размер ячейки, чем в том же объеме памяти, требуется меньше ячеек, что означает, что для идентификатора требуется меньше битов; и наоборот. На аппаратном уровне размер ячейки обычно фиксирован.

Ниже приведен пример для первых 16 байтов в памяти

╔══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╤══════╗ ║ 0000 │ 0001 │ 0010 │ 0011 │ 0100 │ 0101 │ 0110 │ 0111 │ 1000 │ 1001 │ 1010 │ 1011 │ 1100 │ 1101 │ 1110 │ 1111 ║ ╠══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╪══════╣ ║ b0 │ b1 │ b2 │ b3 │ b4 │ b5 │ b6 │ b7 │ b8 │ b9 │ b10 │ b11 │ b12 │ b13 │ b14 │ b15 ║ ╟──────┴──────┼──────┴──────┼──────┴──────┼──────┴──────┼──────┴──────┼──────┴──────┼──────┴──────┼──────┴──────╢ ║ w0 000 │ w1 001 │ w2 010 │ w3 011 │ w4 100 │ w5 101 │ w6 110 │ w7 111 ║ ╟─────────────┴─────────────┼─────────────┴─────────────┼─────────────┴─────────────┼─────────────┴─────────────╢ ║ dw0 00 │ dw1 01 │ dw2 10 │ dw3 11 ║ ╟───────────────────────────┴───────────────────────────┼───────────────────────────┴───────────────────────────╢ ║ o0 │ o1 ║ ╚═══════════════════════════════════════════════════════╧═══════════════════════════════════════════════════════╝ 

Вы также можете посмотреть на иллюстрации в этом ответе

Если мы обращаемся к каждому 2-байтовому слову, тогда N-е слово будет иметь байтовый адрес как N * 2. То же самое для любых других размеров чанка, где реальное смещение может быть вычислено как offset*sizeof(chunk). В результате 2 младших бита в 4-байтовом выровненном адресе 3 младших бита в 8-байтовом выровненном адресе всегда равны нулю. Если вы не используете адресно-адресные указатели, то эти младшие биты можно использовать для хранения данных, которые называются теговыми указателями.

64-битная JVM использует эту технику со сжатыми Oops . См. Хитрость, лежащую в основе сжатых Oops объектов JVM в Java, всегда выровненных по 8 байтов, поэтому они могут адресовать 8 * 4 = 32 ГБ памяти с 32-битным адресом.

Управляемые указатели в куче Java указывают на объекты, которые выровнены по 8-байтовым границам адресов. Сжатые операции представляют управляемые указатели (во многих, но не во всех местах в программном обеспечении JVM) как 32-битные смещения объектов из 64-битного базового адреса кучи Java. Поскольку это смещения объектов, а не смещения байтов, их можно использовать для адресации до четырех миллиардов объектов (не байтов) или размера кучи до 32 гигабайт. Чтобы использовать их, они должны быть масштабированы в 8 раз и добавлены к базовому адресу кучи Java, чтобы найти объект, к которому они относятся. Размеры объектов, использующих сжатые значения, сравнимы с размерами в режиме ILP32.

https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#compressedOop

Инструкции, работающие с немедленным обращением в большинстве архитектур RISC, также хранят слово address, поскольку нет смысла тратить драгоценное пространство, экономя эти всегда нулевые биты. Например, инструкции MIPS для ветвления и перехода : JAL, J, BEQ, BLEZ, BGTZ ...

Похожие вопросы