разыменование нулевого указателя - PullRequest
24 голосов
/ 24 мая 2010
int* p = 0;
int* q = &*p;

Это неопределенное поведение или нет?Я просмотрел некоторые связанные вопросы, но этот конкретный аспект не появился.

Ответы [ 4 ]

50 голосов
/ 24 мая 2010

Ответ на этот вопрос: это зависит от того, какой языковой стандарт вы используете: -).

В C90 и C ++ это недопустимо, потому что вы выполняете косвенное обращение к нулевому указателю (выполняя *p), и это приводит к неопределенному поведению.

Однако в C99 этот является действительным, правильно сформированным и четко определенным. В C99, если операнд унарного - & был получен в результате применения унарного - * или путем выполнения подписки ([]), то ни &, ни *, ни [] применены. Например:

int* p = 0;
int* q = &*p; // In C99, this is equivalent to int* q = p;

Аналогично,

int* p = 0;
int* q = &p[0]; // In C99, this is equivalent to int* q = p + 0;

Из С99 §6.5.3.2 / 3:

Если операнд [унарного оператора &] является результатом унарного оператора *, ни этот оператор, ни оператор & не оцениваются, и результат такой, как если бы оба опущены, за исключением того, что ограничения на операторы все еще применяются, и результат не является lvalue.

Аналогично, если операнд является результатом оператора [], ни оператор &, ни унарный *, подразумеваемый [], не оцениваются, и результат выглядит так, как если бы & оператор был удален, а оператор [] был заменен на оператор +.

(и его сноска № 84):

Таким образом, &*E эквивалентно E (даже если E - нулевой указатель)

3 голосов
/ 24 мая 2010

Да, это было бы неопределенным поведением, но ваш компилятор может оптимизировать &* out.

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

0 голосов
/ 24 мая 2010

ИМХО, что касается двух строк кода, вне адресного пространства нет никакого доступа. Второе утверждение просто берет адрес (* p), который снова будет 'p', и, следовательно, он будет хранить '0'. Но местоположение никогда не доступ .

0 голосов
/ 24 мая 2010

Да, разыменование нулевого указателя является неопределенным поведением.Целочисленная константа 0 в контексте указателя является нулевым указателем.Вот и все.

Теперь, если ваша вторая строка была int *q = p;, это было бы простым указателем.Если компилятор удаляет &* и уменьшает разыменование в присваивании, все в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...