Я не вижу ответов, прямо касающихся того, что я думаю вы спрашивали, так что вот так:
Да, по крайней мере 1 значение адреса «потеряно» (сделано недоступным для использования) из-за константы, используемой для null . Относится ли это к 0 в линейной карте памяти процесса, не имеет значения.
И причина того, что адрес не будет использоваться для хранения данных, заключается в том, что вам нужен особый статус нулевого указателя, чтобы можно было отличить его от любого другого действительного указателя. Как и в случае строк ASCIIZ (C-string, NUL-terminated), где символ NUL обозначается как конец строки символов и не может использоваться внутри строк. Вы можете все еще использовать это внутри? Да, но это введет в заблуждение библиотечные функции в том месте, где заканчивается строка.
Я могу вспомнить, по крайней мере, одну реализацию LISP, которую я изучал, в которой NIL (нуль Лиспа) был не 0, и при этом это был не недействительный адрес, а реальный объект. Причина была очень умной - стандарт требовал, чтобы CAR (NIL) = NIL и CDR (NIL) = NIL (Примечание: CAR (l) возвращает указатель на заголовок / первый элемент списка, где CDR (l) возвращает ptr для хвост / остальная часть списка.). Таким образом, вместо добавления if-проверок в CAR и CDR, является ли указатель NIL - который будет замедлять каждый вызов - они просто выделяли CONS (список мысли) и назначали его голову и хвост, чтобы указывать на себя. Там! - так CAR и CDR будут работать, и этот адрес в памяти не будет использоваться повторно (потому что он берется объектом, заданным как NIL)
пс. я только что вспомнил, что много-много лет назад я читал о некоторой ошибке в Lattice-C, которая была связана с NULL - должно быть, это было в темное время сегментации MS-DOS, когда вы работали с отдельным сегментом кода и сегментом данных - так что я помню возникла проблема, связанная с тем, что первая функция из связанной библиотеки имела адрес 0, поэтому указатель на нее будет считаться недействительным, поскольку == NULL