Intereting Posts
Когда люди сначала начали думать, что «C – портативный ассемблер»? Linux: Захват вывода уже запущенного процесса (в чистом C!) Требуется ли удаление указателя из метода sqlite3_column_blob ()? Преобразование NSDate в String с помощью strftime Ошибка при попытке определить бит 1024 бит (128 байт) Как реализовать исключения с помощью вложенных команд try-catch-finally с сообщениями в C Как маршрутизировать расщепленные пакеты с помощью сетевых фильтров в пространстве ядра Функция C write () не работает Акцентированные / umlauted символы в C? Почему здесь не происходит неявное преобразование из константы в const? CMake make : *** Нет правила, чтобы сделать цель `/path/to/uthash/utarray.h ‘, которая нужна« HelloTest ». Стоп регулярные выражения в C совпадении и печати Как установить пользовательскую точку входа C с помощью Clang на OS X Mavericks? Строка имеет содержимое, даже если нет ввода от пользователя C программа печатает странные символы

Не определено ли поведение неопределенного поведения по адресу неинициализированного указателя?

N1570 утверждает, что это неопределенное поведение:

§J.2 / 1 Значение объекта с автоматической продолжительностью хранения используется, пока оно неопределено (6.2.4, 6.7.9, 6.8).

И в этом случае наш указатель имеет неопределенное значение:

§6.7.9 / 10 Если объект, который имеет автоматическую продолжительность хранения, не инициализируется явно, его значение является неопределенным. Если объект, который имеет статическую или длительность хранения streamов, не инициализируется явно, то:

– если он имеет тип указателя, он инициализируется нулевым указателем;

Тогда я предполагаю, что следующая тестовая программа демонстрирует неопределенное поведение:

#include  int main(void) { char * ptr; printf("%p", (void*)&ptr); } 

Мое мотивирующее беспокойство – функция strtol . Во-первых, позвольте мне процитировать части N1570, связанные с параметром endptr :

§7.22.1.4 / 5 Если последовательность субъекта имеет ожидаемую форму и значение базы равно нулю, последовательность символов, начинающихся с первой цифры, интерпретируется как целочисленная константа в соответствии с правилами 6.4.4.1. […] Указатель на конечную строку хранится в объекте, на который указывает endptr , при условии, что endptr не является нулевым указателем.

§7.22.1.4 / 7 Если последовательность объектов пуста или не имеет ожидаемой формы, преобразование не выполняется; значение nptr сохраняется в объекте, на который указывает endptr , при условии, что endptr не является нулевым указателем.

Это означает, что endptr должен указывать на объект, а также что endptr в какой-то момент разыменовывается. Например, эта реализация делает так :

 if (endptr != 0) *endptr = (char *)(any ? s - 1 : nptr); 

Тем не менее, этот высокоподдерживаемый ответ, а также эта страница человека показывают, что endptr передается strtol uninitialized. Есть ли исключение, которое делает это не неопределенным поведением?

В этом выражении:

&ptr

адрес & операнда, т. е. адрес объекта ptr но объект ptr никогда не оценивается.

(C11, 6.3.2.1p2) «За исключением случаев, когда это операнд оператора sizeof, унарный оператор &, оператор ++, оператор-оператор или левый операнд оператора. Или оператор присваивания, lvalue который не имеет тип массива, преобразуется в значение, хранящееся в указанном объекте (и уже не lvalue), это называется преобразованием lvalue. ”

Значение указателя и его адрес не совпадают.

 void *foo; 

Указатель имеет неопределенное значение, но адрес foo , то есть значение &foo , должен быть хорошо определен (поскольку в противном случае мы не можем получить к нему доступ).

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

Когда вы говорите о коде, эти два иногда путают («что такое адрес этого указателя?» Может означать «каково значение этого указателя, на какой адрес он указывает?»), Но они действительно различны.

См. Этот пример

 char * ptr; 

Поскольку ptr не указывает на какой-либо объект, разыменование его вызывает неопределенное поведение. Но когда вы передаете свой адрес strtol , имея синтаксис

 long int strtol(const char *nptr, char **endptr, int base); 

в заявлении

 long parsed = strtol("11110111", &ptr, 2); 

параметр strtol указывает на объект ptr и отменяет его, не вызывая никакого UB.

Нет. Это не неопределенное поведение. Только ptr неинициализирован и имеет неопределенное значение, но &ptr имеет правильное значение.

Какая стандартная цитата на strtol говорит:

… Если последовательность объектов пуста или не имеет ожидаемой формы, преобразование не выполняется; значение nptr сохраняется в объекте, на который указывает endptr, при условии, что endptr не является нулевым указателем.

Это выше цитаты говорит о вызове, подобном этому:

 strtol(str, 0, 10); 

Вызов на странице руководства и связанный с ним ответ в порядке.

У меня есть только доступ к N1256, но я буду удивлен, если произойдет какое-либо существенное изменение.

Наиболее важным разделом является «6.5.3.2 Операторы адреса и косвенности»

И, в частности, пункт 3 (мой акцент):

Семантика

3 Унарный оператор & дает адрес своего операнда. Если операнд имеет тип ” type ”, результат имеет тип ” указатель на тип ”. Если операнд является результатом унарного * оператора, ни этот оператор, ни оператор & не оцениваются, и результат, как если бы оба были опущены, за исключением того, что ограничения для операторов все еще применяются, а результат не является значением l. Аналогично, если операнд является результатом оператора [], ни оператор &, ни унарный *, который подразумевается [], не оцениваются, а результат выглядит так, как если бы оператор & был удален, а оператор [] был изменен на a +. В противном случае результатом будет указатель на объект или функцию, назначенные его операндом.

Ни один из приведенных абзацев в OP не применяется, поскольку многие из них указали. Значение чего-то и его адреса очень разные.

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

ПРИМЕЧАНИЕ. Мы все знаем, что все в порядке, но очень редко можно найти утверждения в этих стандартах, которые прямо говорят «Да, вы можете так и так».