Что именно означает «разыменование нулевого указателя»? - PullRequest
48 голосов
/ 24 октября 2010

Я полный новичок в C, и во время работы в университете я встречал комментарии в коде, которые часто ссылаются на разыменование пустого указателя. У меня есть опыт работы в C #, я понял, что это может быть похоже на «NullReferenceException», которое вы получаете в .Net, но теперь у меня есть серьезные сомнения.

Может ли кто-нибудь объяснить мне в терминах непрофессионалов, что это такое и почему это плохо?

Ответы [ 5 ]

66 голосов
/ 24 октября 2010
Указатель

A NULL указывает на несуществующую память. Это может быть адрес 0x00000000 или любое другое значение, определяемое реализацией (при условии, что оно никогда не может быть реальным адресом). Разыменование это означает попытку доступа к тому, на что указывает указатель. Оператор * является оператором разыменования:

int a, b, c; // some integers
int *pi;     // a pointer to an integer

a = 5;
pi = &a; // pi points to a
b = *pi; // b is now 5
pi = NULL;
c = *pi; // this is a NULL pointer dereference

Это то же самое, что и NullReferenceException в C #, за исключением того, что указатели в C могут указывать на любой объект данных, даже элементы внутри массива.

28 голосов
/ 24 октября 2010

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

В C унарный оператор * является оператором разыменования. Если x является указателем, то *x - это то, на что указывает x. Унарный оператор & является оператором address-of . Если x является чем-либо, то &x является адресом, по которому x хранится в памяти. Операторы * и & являются обратными друг другу: если x - это какие-либо данные, а y - любой указатель, то эти уравнения всегда выполняются:

*(&x) == x
&(*y) == y

Пустой указатель - это указатель, который не указывает на какие-либо допустимые данные (но это не единственный такой указатель). Стандарт C говорит, что неопределенное поведение для разыменования нулевого указателя. Это означает, что может произойти абсолютно все: программа может аварийно завершить работу, она может продолжать работать тихо или стереть ваш жесткий диск (хотя это маловероятно).

В большинстве реализаций вы получите «ошибку сегментации» или «нарушение доступа», если попытаетесь это сделать, что почти всегда приведет к завершению вашей программы операционной системой. Вот один из способов разыменования нулевого указателя:

int *x = NULL;  // x is a null pointer
int y = *x;     // CRASH: dereference x, trying to read it
*x = 0;         // CRASH: dereference x, trying to write it

И да, разыменование нулевого указателя в значительной степени похоже на NullReferenceException в C # (или NullPointerException в Java), за исключением того, что стандарт langauge здесь немного более полезен. В C # разыменование пустой ссылки имеет четко определенное поведение: оно всегда выдает NullReferenceException. Невозможно, чтобы ваша программа могла продолжать работать в режиме без вывода сообщений или стереть ваш жесткий диск, как в C (если только нет ошибки во время выполнения языка, но опять же это невероятно маловероятно).

2 голосов
/ 24 октября 2010

Это означает

myclass *p = NULL;
*p = ...;  // illegal: dereferencing NULL pointer
... = *p;  // illegal: dereferencing NULL pointer
p->meth(); // illegal: equivalent to (*p).meth(), which is dereferencing NULL pointer

myclass *p = /* some legal, non-NULL pointer */;
*p = ...;  // Ok
... = *p;  // Ok
p->meth(); // Ok, if myclass::meth() exists

в основном, почти все, что связано с (*p) или неявно с участием (*p), например p->..., что является сокращением для (*p). ...;за исключением объявления указателя.

0 голосов
/ 24 октября 2010

Цитирование из wikipedia :

Указатель ссылается на местоположение в памяти, а получение значения в местоположении, на которое ссылается указатель, называется разыменование указатель.

Разыменование выполняется путем применения к указателю оператора unary *.

int x = 5;
int * p;      // pointer declaration
p = &x;       // pointer assignment
*p = 7;       // pointer dereferencing, example 1
int y = *p;   // pointer dereferencing, example 2

«Разыменование нулевого указателя» означает выполнение *p, когда p это NULL

0 голосов
/ 24 октября 2010

С вики

Нулевой указатель имеет зарезервированное значение, часто, но не обязательно, значение ноль, что указывает на то, что он не ссылается на объект
..

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

int val =1;
int *p = NULL;
*p = val; // Whooosh!!!! 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...