Когда константа 0 в контексте указателя приобрела свой особый статус? - PullRequest
14 голосов
/ 20 августа 2011

Как вы знаете, в стандартном современном языке C значение константы 0, используемое в контексте указателя, действует как константа нулевого указателя , которая преобразуется в платформу (и, возможно, даже в тип) значение нулевого указателя .

Между тем, в ранних версиях языка C, описанных в Справочном руководстве по C , не проводилось большого различия между контекстами указателя и целого числа, что позволяло свободно сравнивать и назначать целые числа указателям. , Если я не ошибаюсь, в этой версии C константа 0 не имеет специального статуса, а это означает, что присвоение указателю значения константы 0 будет просто указывать на физический адрес 0 (точно так же, как присвоение указателю значения 42 указать физический адрес 42).

В ANSI C все значительно изменилось. Теперь присвоение указателю константы 0 поместит в этот указатель специфическое для платформы значение нулевого указателя . Значение нулевого указателя не обязательно должно быть представлено физическим значением 0.

Итак, в какой момент истории языка C он изменился с одного на другой? Включил ли K & R C концепцию более высокого уровня нулевого указателя с константой 0, учитывая его особый статус? Или K & R C по-прежнему гарантирует физическое назначение целых чисел даже для константы 0?

Ответы [ 2 ]

8 голосов
/ 20 августа 2011

Возвращается к почти началу C (если не к самому началу).Если вы посмотрите на стр. 21 справочного руководства за январь 1974 г. C , это более или менее прямо указано в некотором примере кода:

/* is pointer null? */
if (p == 0) {

Возвращаясь еще немного дальше к ки.1972-73 Компилятор PDP-11/20 , мы находим:

match(tree, table, nreg)
int tree[], table[]; {
    extern opdope[], dcalc, notcompat;
    int op, d1, d2, t1, t2, p1[], p2[];
    char mp[];

    if (tree==0)
        return(0);
    op = *tree;

По крайней мере, если я правильно читаю, строка if (tree==0) проверяет, что tree не являетсянулевой указатель, прежде чем пытаться разыменовать его.

К сожалению, Деннис говорит , что он не может быть гораздо увереннее в дате, чем "1972-73".

Нетмного истории C до этого.Тем не менее, похоже, что в истории 0 считается нулевым указателем.Мне кажется, что использование 0 в качестве нулевого указателя - это то, что C «унаследовал» от Unix.Запись для exec в ноябрь 1971 г. 1 st Edition Руководство программиста Unix показывает указатель со значением 0, указывающий конец списка аргументов.Согласно описанию Денниса , в этот момент "C еще впереди".

На основании всего этого я бы предположил, что C рассматривал 0 как нулевой указатель с самогоначало, или, по крайней мере, так рано, что, вероятно, больше нет записей о версии языка, которая была бы другой.

Я не был настолько успешен в отслеживании документации о первой точке, когданулевой указатель мог иметь ненулевые биты.С точки зрения языка , никогда не имеет значения.Я подозреваю, что это произошло довольно рано, но найти документацию для поддержки было бы сложно.Один из самых ранних портов C был для мейнфреймов IBM System / 360 , и хотя я не могу найти прямую документацию по этому поводу, моя догадка была бы тем внутренним значением нулевого указателя, которое использовалосьна этих машинах было наверное ненулевое.У меня нет точного числа, но я знаю, что PL / I на этих машинах использовал ненулевое значение для его эквивалента нулевого указателя;Я бы предположил , что когда они портировали C на эти машины, они , вероятно, использовали одно и то же значение.

3 голосов
/ 20 августа 2011

См. Вопрос C-faq 5.4

В качестве стиля многие программисты предпочитают не разбрасывать неукрашенные 0 в своих программах, некоторые из которых представляют числа, а некоторые представляют указатели.Поэтому макрос препроцессора NULL определяется (несколькими заголовками, включая и) как константа нулевого указателя, обычно 0 или ((void *) 0) (см. Также вопрос 5.6).Программист, желающий сделать явное различие между 0 целым числом и 0 константой нулевого указателя, может затем использовать NULL всякий раз, когда требуется нулевой указатель.

Использование NULL является только стилистическим соглашением;препроцессор превращает NULL обратно в 0, который затем распознается компилятором в контексте указателя, как и раньше.В частности, приведение может быть необходимо до NULL (как и до 0) в аргументе вызова функции.Таблица под вопросом 5.2 выше применяется как к NULL, так и к 0 (неукрашенный NULL эквивалентен неукрашенному 0).

NULL следует использовать только в качестве константы указателя;см. вопрос 5.9.

References: K&R1 Sec. 5.4 pp. 97-8
K&R2 Sec. 5.4 p. 102
ISO Sec. 7.1.6, Sec. 6.2.2.3
Rationale Sec. 4.1.5
H&S Sec. 5.3.2 p. 122, Sec. 11.1 p. 292 

Что это за печально известный нулевой указатель?

В определении языка говорится, что для каждого типа указателя существуетэто специальное значение - «нулевой указатель», - которое можно отличить от всех других значений указателя и которое «гарантированно сравнивает неравное с указателем на любой объект или функцию».То есть нулевой указатель нигде не указывает;это не адрес какого-либо объекта или функции.Оператор address-of & никогда не выдаст нулевой указатель, как и успешный вызов malloc. [Footnote] (malloc действительно возвращает нулевой указатель в случае сбоя, и это типичное использование нулевых указателей: в качестве «специального»).значение указателя с некоторым другим значением, обычно «не выделено» или «еще никуда не указывает».)

Нулевой указатель концептуально отличается от неинициализированного указателя.Известно, что нулевой указатель не указывает на какой-либо объект или функцию;неинициализированный указатель может указывать куда угодно.См. Также вопросы 1.30, 7.1 и 7.31.

Как упоминалось выше, для каждого типа указателя имеется нулевой указатель, и внутренние значения нулевых указателей для разных типов могут различаться.Хотя программистам не нужно знать внутренние значения, компилятор всегда должен быть информирован о том, какой тип нулевого указателя требуется, чтобы он мог провести различие при необходимости (см. Вопросы 5.2, 5.5 и 5.6).

References: K&R1 Sec. 5.4 pp. 97-8
K&R2 Sec. 5.4 p. 102
ISO Sec. 6.2.2.3
Rationale Sec. 3.2.2.3
H&S Sec. 5.3.2 pp. 121-3

Наконец, только константа целочисленные выражения со значением 0 гарантированно указывают на нулевые указатели.

...