На 32-битной машине, почему размер указателя 32-бит? Почему не 16-битный или 64-битный? Какие минусы и плюсы?
Почему размер указателя составляет 4 байта в С++
Ответ 1
Потому что он имитирует размер фактических "указателей" в ассемблере. На машине с 64-разрядной адресной шиной она будет 64 бит. В старых 6502 это была 8-разрядная машина, но у нее была 16-разрядная адресная шина, чтобы она могла адресовать 64 КБ памяти. На большинстве 32-битных машинах было достаточно 32 бит для адресации всей памяти, так что размер указателя был на С++. Я знаю, что некоторые из ранних чипов серии M68000 имели только 24-битное адресное пространство памяти, но оно было адресовано из 32-битного регистра, поэтому даже на тех, у которых указатель будет 32 бита.
В плохие старые дни 80286 было хуже - существовал 16-разрядный адресный регистр и 16-разрядный сегментный регистр. Некоторые компиляторы С++ не скрывали это от вас и заставили вас объявить ваши указатели как near
или far
в зависимости от того, хотите ли вы изменить регистр сегментов. К счастью, я переработал большинство этих клеток мозга, поэтому я забыл, что указатели near
были 16 бит, но на уровне машины они были бы.
Ответ 2
Размер указателя в С++ определяется реализацией. С++ может работать на чем угодно, от вашего тостерного чипа до огромных мэйнфреймов. Для разных архитектур требуются разные типы данных.
Если на вашей реализации указатель 32-битный, то это, скорее всего, архитектура, которая может адресовать 2 ^ 32 байта. (Обратите внимание, что даже размер байтов может отличаться в зависимости от реализации.) 64-битные архитектуры обычно могут адресовать 2 ^ 64 байта, поэтому реализации на этих архитектурах, скорее всего, будут иметь размер указателя 64 бит.
Ответ 3
16 бит, очевидно, будет недостаточным - вы могли бы только адресовать 64K.
Почему бы не эмулировать 64-битную систему на 32-битных системах - я думаю, потому что производительность арифметики указателя ухудшится.
Ответ 4
Как упоминалось во многих других ответах, размер указателя не обязательно должен быть 32-битным - реализация установит размер указателя на то, что диктует архитектура платформы. В системе с 64-разрядной адресацией размер указателя обычно будет 64-битным.
Однако следует также отметить, что даже в одной реализации разные типы указателей могут иметь разные размеры. В частности, типы указателя на элемент (которые я дам - указатели с нечетным шаром) могут иметь разные размеры, чем простые указатели на объекты.
То же самое касается указателей на простые старые функции - они могут иметь разный размер, чем указатели на объекты (это относится как к C, так и к С++). Однако на современных настольных системах вы обычно обнаружите, что указатели на функции имеют тот же размер, что и указатели на объекты.
Вот краткий пример забавы с функциями-указателями-членами:
#include <stdio.h>
class A {};
class B {};
class VirtD: public virtual A, public virtual B {
public:
virtual int Dfunc() { return 5; };
};
typedef int (VirtD::* Derived_mfp)();
int main()
{
VirtD virtd;
Derived_mfp mfp = &VirtD::Dfunc;
printf( "sizeof( mfp) == %u\n", (unsigned int) sizeof( mfp));
}
Отображает: sizeof (mfp) == 12 на MSVC.
Ответ 5
Размер указателя имеет мало общего с архитектурой (32 бит, 64 бит). 32bit обычно ссылается на то, что размер регистра 32 бит. В результате максимально возможное количество адресов, которые вы можете использовать с помощью одного регистра, 2^32
. Таким образом, это сводится к эффективности адресации слотов памяти с использованием регистра.
Ответ 6
С 32-разрядным указателем вы можете указать более широкий диапазон памяти, чем с 16-разрядными указателями. Когда 32-разрядные указатели были стандартизованы, 64-разрядные процессоры были не очень популярны (или даже существуют?). Поэтому указатель не сможет вписаться в регистр CPU, что является очень важным фактором для скорости.
Ответ 7
Чтобы ответить на ваш вопрос: сам С++ очень мало говорит о размере указателя и, конечно же, не о том, что он должен быть 32 бита или что-то еще. Размер указателя должен быть естественным для архитектуры машины.
Ответ 8
Почему не 16-бит? Поскольку, предполагая плоское 32-разрядное адресное пространство, вы не можете адресовать каждый байт. Вдали от него: вы можете адресовать только 2 16 уникальные местоположения с 16-разрядным указателем. Даже если ваши указатели указывают только на слова, а не байты, это все равно оставляет 1073676288 несовпадающих слов.
Предполагая плоское 32-разрядное адресное пространство, вы уже можете обращаться к каждому байту с 32-разрядным указателем. На данный момент 64-битные указатели просто теряют пространство, если вы не хотите добавлять дополнительную информацию к каждому указателю. Например, на 32-битной PowerPC дескриптор функции на самом деле является 96-битным сущностью, причем одна треть указывает на исполняемый код, а остальные - данные, которые облегчают перемещение модулей.
В сегментированном адресном пространстве могут быть полезны более крупные, чем 32-разрядные указатели на данные. Windows NT на DEC Alpha была 32-разрядной операционной системой, но оборудование Alpha было 64-битным. Ваше обычное адресное пространство все еще было 32-битным, но были специальные API-интерфейсы, позволяющие 32-разрядным программам обращаться к 64-разрядным адресам, как если бы они находились в недоступных для других сегментах.