Что такое пустой указатель и что такое нулевой указатель? - PullRequest
36 голосов
/ 02 декабря 2010

Итак, я проходил через несколько вопросов об интервью и наткнулся на один о пустых и нулевых указателях , который утверждает:

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

Это сильно смутило меня!Кажется, что void и null могут использоваться взаимозаменяемо в соответствии с этим вопросом, и я не считаю, что это правильно.Я предположил, что void является типом возвращаемого значения, а null - значением.Но я просто новичок в коде и не уверен, что прав.

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

Ответы [ 9 ]

42 голосов
/ 02 декабря 2010

Два понятия ортогональны:

  1. Пустой указатель (void *) является необработанным указателем на какую-то ячейку памяти.
  2. Нулевой указатель - это специальный указатель, который по определению ни на что не указывает. Это может быть указатель на любой тип, void или другой.

Пустой указатель может быть нулевым или нет:

void *void_ptr1 = nullptr;
void *void_ptr2 = malloc(42);
void *void_ptr3 = new Foo;               // void * can point to almost anything
void *void_ptr4 = (char*)void_ptr3 + 1;  // even somewhere inside an object

Не пустой указатель также может быть нулевым или нет:

Foo *f = nullptr;
Foo *g = new Foo;
29 голосов
/ 02 декабря 2010

Просто забудь об этом ответе. Цитата из вашей ссылки:

"указатель без типа возврата называется нулевым указателем. "

Это ооочень просто НЕПРАВИЛЬНО . Указатель тип возвращаемого значения ? ДЕЙСТВИТЕЛЬНО? Это плохой источник ...

void* является универсальным указателем type , поскольку любой тип указателя (кроме указателя на const и / или volatile) может быть неявно преобразован в void*. Другими словами, вы можете назначить любой указатель на переменную типа void*. Нулевой указатель - это указатель значение 0

16 голосов
/ 02 декабря 2010

Тип void в общем случае означает, что информация о типе не указывается.

Следует всегда иметь в виду, что указатель передает две части информации: тип указанногоdata (int, double, ...), который определяет, как его интерпретировать, и адрес данных, на которые он указывает, который указывает , где вы можете получитьфактическое значение указанных данных.

Информация о типе указана в типе указателя (double*, int*, ...), в то время как адрес данных является фактическим значением, содержащимся в переменной указателя.

Таким образом, указатель void (void *) является указателем, который не указывает никакой информации о типе,Он говорит вам, где находятся данные, но не говорит, как их интерпретировать.Вы знаете, что по этому адресу есть что-то, но вы не знаете, является ли это int, double или массивом летающих коров.Чтобы на самом деле использовать такие данные, вы должны получить информацию о типе об этом каким-то другим способом (например, с каким-то другим магическим параметром), привести этот указатель к обычному типу указателя и затем использовать его как обычно.* часто используется в C для поддержки своего рода общего программирования;см., например, библиотечную функцию qsort C.

Указатель NULL вместо этого - указатель, который ничего не указывает.В этом случае информация о типе указателя в целом присутствует, но отсутствует адрес указанных данных.Конечно, возможно иметь void *, то есть NULL.

Быстрый пример (предположим, что v объявлен как double v;):

                         Type information present
             +----------------------+----------------------+
             |          ✔           |          ✘           |
         +---+----------------------+----------------------+
    p  c |   |                      |                      |
 v  o  o | ✔ | double * ptr = &v;   | void * ptr = &v;     |
 a  i  n |   |                      |                      |
 l  n  t +---+----------------------+----------------------+
 i  t  e |   |                      |                      |
 d  e  n | ✘ | double * ptr = NULL; | void * ptr = NULL;   |
    d  t |   |                      |                      |
         +---+----------------------+----------------------+

Викторины : NULL, по крайней мере в текущем стандарте, гарантированно будет равно 0.

В других областях языка void всегда используется для указанияотсутствие типа.Использование его в качестве возвращаемого значения (примечание: я сейчас говорю о void, а не void *) означает, что функция не возвращает никакого значения, а приведение выражения к void - это причудливый способ отбросить значение (выповторно сообщите компилятору и другим программистам, что вы осознаете, что не используете определенное значение).

10 голосов
/ 02 декабря 2010

Пожалуйста, сообщите нам: в чем разница:

  • между ситуацией с бензобаком и без газа
  • между банкой с печеньем и без печенья
  • между сроками«деньги» и «пустые карманы»

Если вы придумаете это, вы сможете понять ноль против пустоты * диллема.

9 голосов
/ 02 декабря 2010

void не относится к типу. null не является значением.

3 голосов
/ 02 декабря 2010

Вот некоторые различия в отношении арифметики указателей:

Это связано с тем, что void является неполным типом.

void *vp;
vp++;     // error, incomplete type
vp += 2;  // same error

void *p = 0;
p++;      // still same error

int *p = 0;
p++;      // well-formed program, but UB ($5.6/5)
2 голосов
/ 02 декабря 2010

Ссылка на статью просто неверна.Его первое предложение:

указатель без типа возврата называется нулевым указателем

вызывает для меня все виды аварий.Это очень запутанная часть письма.

Вы почти правы.«Указатель на пустоту» - это тип (не «тип возврата»).Значения любого типа могут быть возвращены функциями, и, таким образом, могут быть возвращены (функции) возвращаемого типа.

Пустой указатель - это указатель, который независимо от его типа указывает на нулевой объект, который не являетсядопустимый объект, который может быть создан.Можно сказать, что нулевой указатель указывает на «ничто».

Указатель на void также может быть нулевым;

void *nothing = 0;

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

1 голос
/ 24 сентября 2016

A void *ptr - указатель, который может использоваться для указания любого типа данных. Это может быть int, float, double. Он не имеет возвращаемого типа, так как изначально указатель создается с указателем типа (имеющим шестнадцатеричное значение), и мы можем присвоить этот указатель любому типу данных.

В то время как нулевой указатель является указателем, имеющим в качестве адреса значение NULL, указателю присваивается значение NULL, поэтому его нельзя использовать для доступа к другим данным, которые его адрес может содержать при создании. Я думаю, что это хорошая методика программирования - указатель NULL, если он не используется в данный момент.

1 голос
/ 02 декабря 2010

нулевой указатель указывает на 0x000000 (что неверно для доступа к указателю), а пустой указатель является правильным указателем на неопределенный тип (void *).Тем не менее, указатель void может быть нулевым указателем, но тогда ссылка на указатель приведет к ошибке.

...