Не может быть неопределенным, потому что там char может быть представление ловушки, потому что 6.2.6.1p5 говорит, что доступ ко всему с символьным типом хорошо определен.
Это могло быть неопределенным из-за 6.3.2.1p2
Lvalue, обозначающее объект с автоматической продолжительностью хранения, который мог быть объявлен с классом хранения регистров, используется в контексте, который требует значения назначенного объекта, но объект не инициализирован.
Итак, вопрос в том, мог ли массив быть объявлен с классом хранения регистров?
Ответ на этот вопрос - нет, не могло быть, потому что вы индексируете его. Индексирование определяется в соответствии с 6.5.2.1p2
(
Постфиксное выражение, за которым следует выражение в квадратных скобках [], является индексированным обозначением элемента объекта массива. Определение оператора индекса [] заключается в том, что E1 [E2] идентично (* ((E1) + (E2))). Из-за правил преобразования, которые применяются к бинарному оператору +, если E1 является объектом массива (эквивалентно указателем на начальный элемент объекта массива), а E2 является целым числом, E1 [E2] обозначает E2-й элемент E1 (отсчет с нуля). )
с точки зрения покрытия массива до адреса его первого элемента, но для массива, классифицированного по регистрам, такое преобразование не было бы определено согласно пункту маркированного списка:
Значение lvalue, имеющее тип массива, преобразуется в указатель на начальный элемент массива, а объект массива имеет класс хранения регистров (6.3.2.1).
в приложении J.2 Неопределенное поведение, что означает массив не мог быть объявлен register
.
Сноска 121 в 6.7.1 Спецификаторы класса хранения уточняют это:
адрес любой части объекта, объявленного с помощью регистра спецификатора класса хранения, не может быть вычислен ни явно (с использованием унарного оператора &, как описано в 6.5.3.2), ни неявно (путем преобразования имени массива в указатель, как описано в 6.3.2.1). Таким образом, единственные операторы, которые могут быть применены к массиву, объявленному с регистром спецификатора класса хранения, - это sizeof и _Alignof.
(Другими словами, хотя язык допускает регистровые массивы, они по существу непригодны для использования).
Следовательно, код вроде:
char unspecified(void){ char s[1]; return s[0]; }
вернет неопределенное значение, но не сделает поведение вашей программы неопределенным.
person
PSkocik
schedule
04.05.2018
s[4]
никогда не был назначен, поэтому мы находимся в той же ситуации, что и в строкеchar v1 = s[0]; // UB
.strcpy
назначает здесь толькоs[0]
s[3]
. - person Jabberwocky   schedule 04.05.2018char
гарантирует отсутствие значения представления ловушки (если я правильно помню), значение просто неопределенное. Итак, хорошо определенное - это слишком много, я скажу, что оно определено реализацией и, как правило, оно будет просто содержать значение мусора. - person Stargateur   schedule 04.05.2018unsigned char
, но не его подписанная версия или версия с неизвестной подписью. - person iBug   schedule 04.05.2018unsigned char
. Однако параграф C 2011, в котором говорится, что чтение объекта, имеющего представление прерывания, является неопределенным поведением, 6.2.6.1 5, в частности, исключает символьные типы. Таким образом, чтение символа, имеющего представление прерывания, не считается неопределенным. - person Eric Postpischil   schedule 04.05.2018int
. (б) Ваша посылка ошибочна.char v1 = s[0];
не имеет неопределенного поведения. - person Eric Postpischil   schedule 04.05.2018vx
переменных не является UB. Все либо четко определено, либо содержит неопределенные значения? - person iBug   schedule 04.05.2018s
никогда не берется,s[0]
- это UB вfoo()
, я думаю. - person Stargateur   schedule 04.05.2018register
. Вопрос в том, как это преобразовать в массивы? Кажется, что массивы объявляются с помощьюregister
, но в приложении J2 говорится, что UB должен преобразовывать классифицированный регистром массив в его первый член, но такое преобразование определяется тем, как определяется индексирование, поэтому кажется, что массивы, объявленные регистром, не индексируются, но поскольку вы индексируете, массив не может быть объявлен регистром, поэтому разыменования должны давать неопределенные значения, но не приводить к UB. Хотя это странно. - person PSkocik   schedule 04.05.2018s[0]
определяется стандартом C как(*)((s)+(0))
.(s)+(0)
- это адресs[0]
. У него есть адрес, поэтому не может бытьregister
. - person Eric Postpischil   schedule 04.05.2018s
не является адресомs
aka _3 _... Это сам массив, который вы должны взять адрес, а не один из его адресов значений;) но что бы PSkocik ни дал прекрасное объяснение, что это не UB, потому что у массива не может быть квалификатора регистра. - person Stargateur   schedule 04.05.2018sizeof
. - person Eric Postpischil   schedule 04.05.2018s[] = { 'f', 'o, 'o', '\0' };
.strcpy
копирует терминатор NUL. Об этом четко сказано в документации. - person Jabberwocky   schedule 04.05.2018register
ключевое слово для запроса такого хранилища. С другой стороны, они также не хотели требовать, чтобы реализации принимали такой код. Стандартный способ описания функций, которые реализации могут поддерживать, но не обязательны, - это классифицировать эти функции как неопределенное поведение. - person supercat   schedule 05.05.2018