Помните, что во всех обычных случаях вы не видите конкретных адресов.
Когда вы выделяете память, ОС предоставляет вам адрес этого блока памяти.
Когда вы берете ссылку на переменную, переменная уже была размещена по адресу, определенному системой.
Таким образом, доступ к нулевому адресу на самом деле не является проблемой, потому что, когда вы следуете указателю, вам все равно, на какой адрес он указывает, только то, что он действителен:
int* i = new int(); // suppose this returns a pointer to address zero
*i = 42; // now we're accessing address zero, writing the value 42 to it
Итак, , если вам нужен нулевой адрес, он, как правило, будет работать нормально.
Значение 0 == null действительно становится проблемой, только если по какой-то причине вы обращаетесь к физической памяти напрямую. Возможно, вы пишете ядро ОС или что-то в этом роде самостоятельно. В этом случае вы будете выполнять запись по определенным адресам памяти (особенно по тем, которые сопоставлены с аппаратными регистрами), и, таким образом, вам, вероятно, может потребоваться запись по нулевому адресу. Но тогда вы действительно обходите C ++ и полагаетесь на специфику вашего компилятора и аппаратной платформы.
Конечно, если вам нужно написать по адресу ноль, это возможно. Только константа 0
представляет нулевой указатель. Непостоянное целочисленное значение, равное нулю, не будет, если назначено указателю, дать нулевой указатель.
Так что вы можете просто сделать что-то вроде этого:
int i = 0;
int* zeroaddr = (int*)i;
теперь zeroaddr будет указывать на адрес ноль (*), но, строго говоря, он не будет нулевым указателем, поскольку нулевое значение не было постоянным.
(*): это не полностью правда. Стандарт C ++ гарантирует только «определяемое реализацией отображение» между целыми числами и адресами. Он может преобразовать 0 в адрес 0x1633de20` или любой другой адрес, который ему нравится. Но сопоставление обычно является интуитивно понятным и очевидным, где целое число 0 сопоставляется с нулевым адресом)