Если указатель на указатель равен NULL, то необходимо ли указатель также иметь значение NULL? - PullRequest
4 голосов
/ 20 сентября 2019

Предположим, у меня есть структура

typedef struct point_t
{
  int x;
  int y;
}POINT;

Я создаю указатель на указатель для POINT и инициализирую его как NULL.

POINT **ppPoint = NULL;

Если *ppPoint также возвращает NULL?

Ответы [ 4 ]

11 голосов
/ 20 сентября 2019

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

Учтите это:

int *p = NULL; // modern practice would be to use nullptr anyway

if (0 == *p) // this is Undefined Behaviour!
{
    // do something, maybe?
}

Вы просто добавляете к этому еще один слой, где вместо int,у вас есть point_t*, но это действительно не имеет значения.

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

3 голосов
/ 20 сентября 2019

Во-первых, существуют обычные заблуждения о таинственном нуле.В этом случае есть 3 связанных термина:

  • нулевой указатель
  • константа нулевого указателя
  • NULLmacro

Константа нулевого указателя - это целое число 0 или это целое число, приведенное к указателю (void*)0.Макрос NULL гарантированно будет переносимой константой нулевого указателя.

Всякий раз, когда вы назначаете константу нулевого указателя, например NULL, любому указателю, этот указатель становится нулевым указателем .Это позволяет компиляторам внутренне представлять нулевой указатель как нечто иное, чем 0, потому что адрес 0x00...00 часто является допустимым физическим адресом во многих системах.

В частности, C17 6.3.2.3/3 определяет это:

Целочисленное константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя .Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевой указатель , гарантированно сравнивается с неравным указателем на любой объект или функцию.


При обращении к нулевому указателю путем разыменования его, с не получить никакого предсказуемого результата.Это неопределенное поведение в соответствии с C17 6.5.3.2/4:

Если указателю было присвоено недопустимое значение, поведение унарного оператора * не определено.

Значит, может случиться что угодно.Если вам повезет, вы просто получите сбой системы.

Однако вы можете сравнить нулевой указатель с другим нулевым указателем или с константой нулевого указателя, и они гарантированно будут равны (C17 6.5.9).

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

3 голосов
/ 20 сентября 2019

Нулевой указатель не указывает на что-либо .Это относится как к обычным указателям, так и к указателям на функции.Это также относится к указателям на указатели.

Поэтому нет смысла говорить о значении «на что он указывает».

3 голосов
/ 20 сентября 2019

Вы не можете разыменовать указатель со значением NULL.Таким образом, вы не сможете получить доступ к *ppPoint.

. Вы можете проверить адрес переменной с помощью %p в формате printf() для проверки.

printf("Address of ppPoint: %p", *ppPoint);
printf("Address of *ppPoint: %p", *ppPoint);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...