Я только начал использовать С++ и увидел, что это нулевое значение для указателей. Мне интересно, для чего это используется. Кажется, что было бы бессмысленно добавлять указатель, указывающий на ничто.
Для чего используются нулевые указатели
Ответы (5)
Что ж, значение нулевого указателя имеет замечательное свойство: несмотря на то, что оно является четко определенным и уникальным постоянным значением, точное значение зависит от машинной архитектуры и ABI (на большинстве современных все биты-ноль, не то, чтобы это имело значение) , он никогда не указывает на объект (или сразу за ним).
Это позволяет использовать его в качестве надежного индикатора ошибки, когда ожидается допустимый указатель (функции могут вместо этого выдать исключение или завершить выполнение), а также в качестве контрольного значения или для обозначения отсутствия чего-то необязательного.
Во многих реализациях доступ к памяти через нулевой указатель надежно вызовет аппаратное исключение (некоторые даже перехватывают арифметику), хотя во многих других, особенно без подкачки и/или сегментации, этого не произойдет.
Кажется, что было бы бессмысленно добавлять указатель, указывающий на ничто.
Нет это не так. Предположим, у вас есть функция, возвращающая необязательное динамически выделяемое значение. Когда вы хотите вернуть «ничего», вы возвращаете ноль. Вызывающий может проверить значение null и различать два разных случая: когда возвращаемое значение равно "ничего" и когда возвращаемое значение является допустимым пригодным для использования объектом.
Как правило, это заполнитель. Если вы просто объявите указатель int *a;
, нет гарантии, что находится в указателе, когда вы захотите получить к нему доступ. Поэтому, если ваш код может или не может установить указатель позже, нет никакого способа определить, является ли указатель действительным или просто указывает на мусорную память. Но если вы объявите его как NULL
, например int *a = NULL;
, вы сможете позже проверить, был ли установлен указатель, например if(a == NULL)
.
Большую часть времени во время инициализации мы присваиваем нулевое значение указателю, чтобы мы могли проверить, является ли он все еще нулевым или ему был назначен адрес или нет.
nullptr
.
- person tadman; 14.03.2018
null
.
- person Deduplicator; 14.03.2018
null значение в C и C++ равно 0. Но nullptr
в C++ отличается от него, nullptr всегда является типом указателя в C++. Мы присваиваем нулевое значение переменной-указателю по разным причинам.
- Чтобы проверить, была ли выделена память для указателя или нет
- Чтобы нейтрализовать висячий указатель, чтобы он не создавал никаких побочных эффектов
- Чтобы проверить, является ли обратный адрес действительным адресом или нет и т. д.
Большую часть времени во время инициализации мы присваиваем нулевое значение указателю, чтобы мы могли проверить, является ли он все еще нулевым или ему был назначен адрес или нет.
nullptr
в C++ отличается от него. Это звучит неправильно. Можете ли вы уточнить?
- person HolyBlackCat; 14.03.2018
nullptr
не является типом указателя. *nullptr
неправильно сформирован.
- person eerorika; 14.03.2018
По сути, указатели — это просто целые числа. Нулевой указатель — это указатель со значением 0. Он не указывает строго ни на что, он указывает на абсолютный адрес 0, который обычно недоступен для вашей программы; разыменование вызывает ошибку.
Обычно он используется в качестве значения флага, так что вы можете, например, использовать его для завершения цикла.
Обновление:
Кажется, многие люди сбиты с толку этим ответом, который, строго говоря, совершенно правильный. См. C11(ISO/IEC 9899:201x) §6.3.2.3 Указатели Раздел 3:
Целое константное выражение со значением 0 или такое выражение, приведенное к типу void *, называется константой нулевого указателя. Если константа нулевого указателя преобразуется в тип указателя, результирующий указатель, называемый нулевым указателем, гарантированно будет сравниваться с неравным указателю на любой объект или функцию.
Итак, что такое адрес? Это число n, где 0 ≤ n ≤ max_address
. И как представить такое число? Да ведь это целое число, как и говорит стандарт.
Стандарт C11 ясно дает понять, что по адресу 0 никогда не на что ссылаться, потому что в каком-то старом патологически непереносимом коде в BSD 4.2 вы часто видели такой код:
/* DON'T TRY THIS AT HOME */
int
main(){
char target[100] ;
char * tp = &target ;
char * src = "This won't do what you think." ;
void exit(int);
while((*tp++ = *src++))
;
exit(0);
}
Это все еще действует C:
$ gcc -o dumb dumb.c
dumb.c:6:12: warning: incompatible pointer types initializing 'char *' with an
expression of type 'char (*)[100]' [-Wincompatible-pointer-types]
char * tp = &target ;
^ ~~~~~~~
1 warning generated.
$
В 4.2BSD на VAX такая чепуха могла сойти с рук, потому что адрес 0
надежно содержал значение 0, поэтому присваивание оценивалось как 0
, что, конечно же, ЛОЖЬ.
Теперь для демонстрации:
/* Very simple program dereferencing a NULL pointer. */
int
main() {
int * a_pointer ;
int a_value ;
void exit(int); /* To avoid any #includes */
a_pointer = ((void*)0);
a_value = *a_pointer ;
exit(0);
}
Вот результаты:
$ gcc -o null null.c
$ ./null
Segmentation fault: 11
$
nullptr
) иногда можно вызвать метод, который не использует какие-либо переменные-члены, по указателю nullptr
class
.
- person Algirdas Preidžius; 14.03.2018
0
. Это обычно недоступно, поэтому вызывает ошибку. - person Charlie Martin   schedule 14.03.2018nullptr
, а не вызывает ошибку. - person Algirdas Preidžius   schedule 14.03.2018nullptr
это не присвоенное значение типа. - person tadman   schedule 14.03.2018nullptr
до тех пор, пока не появится фактическое значение для присвоения. - person tadman   schedule 14.03.2018nullptr
лучше, чем ничего, так как позже вы можете проверить, присвоено ли оно или нет, вместо того, чтобы не знать. - person tadman   schedule 14.03.2018nullptr
четко определено. - person Passer By   schedule 14.03.2018