Является ли чтение неопределенным значением undefined поведения?

Вопрос возник в комментариях к ответе на вопрос Является ли тип bool типа C/С++ всегда равным 0 или 1, если typecast'ed для int?

В рассматриваемом коде выделяется (локальный) массив bool без инициализации их значения.

const int n = 100;
bool b[n];

Ясно, что значения в b являются неопределенными.

Некоторые из комментаторов высказали мнение, что чтение, например, b[0] было undefined. Это указано где-либо в стандарте С++? Я все еще убежден в обратном:

  • Очевидно, что выделено хранилище, и инициализация базового типа bool завершена, так как у него нет конструктора. Это, конечно, не то же самое, что разыменование неинициализированного указателя или вызов методов/операторов приведения на неинициализированных нетривиальных объектах. Эти конкретные случаи, как представляется, охватываются стандартом.

  • Поведение действительно undefined в C: Что происходит с объявленной, неинициализированной переменной в C? Имеет ли это значение?, и некоторые респонденты, похоже, путают эти два.

  • В последнем проекте С++ 0x я не могу найти определение неопределенного значения, в частности, определение, позволяющее получить доступ к такому значению для запуска ловушки процессора. В самом деле, Бьярне Страуструп не уверен, что может иметь значение inderminate: http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

Ответ 1

да, формально преобразование значения неопределенного значения равно UB (за исключением unsigned char, изначально я написал "и варианты", но, как я помню, формальный обслуживает 1 дополнение, подписанное char, где возможно минус 0 может использоваться как значение ловушки)

Я слишком ленив, чтобы выполнить стандартный поиск параграфа для вас, а также лениться заботиться о downvotes для этого

однако на практике только проблема на (1) архаичных архитектурах и, возможно, (2) 64-битных системах.

РЕДАКТИРОВАТЬ: oops, теперь я, кажется, вспоминаю сообщение в блоге и связанный с ним отчет о дефектах о формальном UB для доступа к неопределенному char. так что, возможно, мне придется проверять стандартные, + поисковые DR. argh, это должно быть позже, теперь кофе!

EDIT2: Johannes Schaub был достаточно любезен, чтобы предоставить ссылку на вопрос SO, где обсуждался этот UB для доступа к char. Итак, что, где я это помню! Спасибо, Йоханнес.

приветствия и hth.,

Ответ 2

Ответ на этот вопрос меняется с помощью последнего рабочего проекта С++ 1y (N3946), который можно найти здесь здесь. Раздел 8.5 Параметр инициализаторов 12 сильно меняется с С++ 03 и С++ 11 и теперь содержит следующее (выделение):

Если для объекта не задан инициализатор, объект по умолчанию инициализируется. При хранении для объекта с автоматическим или динамическая длительность хранения, объект имеет неопределенный значение, и если для объекта не выполняется инициализация, это объект сохраняет неопределенное значение до тех пор, пока это значение не будет заменено (5.17). [Примечание. Объекты со статической или длительностью хранения потоков нулевой инициализации, см. 3.6.2. - end note] Если неопределенное значение равно по результатам оценки, undefined, за исключением следующие случаи:

и далее перечисляет некоторые исключения только для неподписанного типа узкого символа, у меня есть полная цитата в Изменена ли С++ 1y относительно использования неопределенных значений и undefined поведение?.

Итак, в вашем случае b имеет автоматическую продолжительность хранения и не инициализируется и поэтому имеет неопределенное значение. Поэтому оценка b[0] действительно undefined.

Раньше нам приходилось использовать преобразование lvalue-to-rval, чтобы доказать, что это было undefined, но это проблематично, поскольку преобразование указано ниже.

Обратите внимание, что неопределенное значение выделено курсивом в этом разделе, и поэтому оно означает, что оно определено на месте, и теперь С++ 1y фактически определяет этот термин. Раньше этот термин использовался без определения, это описано в отчете о дефектах 616.

Ответ 3

В bool стандарт говорит в 3.9.1 Основные типы:

Значения типа bool являются либо истинными, либо ложь.

С примечанием:

Использование значения bool описанными способами настоящим Международным стандартом "undefined," , например, путем изучения значение неинициализированной автоматической объект, может привести к тому, что он будет вести себя , как если бы он не является ни истинным, ни ложным.

Ответ 4

Тот факт, что чтение неопределенного значения обычно приводит к Undefined Поведение - это не просто "теоретическая" проблема. Даже для типов, где все возможные битовые шаблоны имеют определенные значения, не следует считать "неожиданным" для неопределенных значений вести себя так, чтобы они отличались от значений Unspecified. Например, если * p содержит неопределенное значение, а x не используется нигде, кроме как показано, код:

uint32_t x,y,z;
...
x = *p;
if (condition1) y=x;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=x;

можно переписать как:

if (condition1) y=*p;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=*p;

Если значение * p является неопределенным, компилятор не будет запрещен из-за того, что код между двумя операторами "if" изменяет его значение. Например, если хранилище, занятое * p, занято "float" прежде чем он освободится и переделан, компилятор может написать, что "плавать", значение между двумя приведенными выше операциями if.