Представления ловушек
Что: Как указано в [C17 §6.2.6.1 / 5], представление ловушек не является значением. Это битовый шаблон, который заполняет пространство, выделенное для объекта данного типа, но этот шаблон не соответствует значению этого типа. Это специальный шаблон, который можно распознать с целью запуска поведения, определенного реализацией. То есть поведение не охватывается стандартом, что означает, что оно попадает под баннер «неопределенного поведения». Стандарт устанавливает возможности для того, когда ловушка может быть (не должна быть) запущена, но он не пытается ограничить то, что ловушка может делать. Для получения дополнительной информации см. A: представление ловушки .
Неопределенное поведение, связанное с представлением ловушки, интересно тем, что реализация должна его проверять. Более распространенные случаи неопределенного поведения были оставлены неопределенными, поэтому реализации не должны проверять их. Необходимость проверки представлений прерываний является хорошей причиной для того, чтобы в эффективной реализации требовалось несколько представлений прерываний.
Кто: Решение о том, какие битовые комбинации (если таковые имеются) составляют представления прерываний, сводится к реализация. Стандарты не навязывают существование представлений ловушек; когда упоминаются представления ловушек, формулировка является разрешающей, как в «может быть», в отличие от требовательной, как в «должно быть». Представления ловушек разрешены, не обязательны. Фактически, N2091 пришел к выводу, что представления ловушек практически не используются на практике, что привело к предложению исключить их из стандарта C. (Он также предлагает план резервного копирования, если удаление оказывается невозможным: явным образом укажите, что реализации должны задокументировать, какие представления являются представлениями прерываний, поскольку нет другого способа точно узнать, является ли данный битовый шаблон представлением прерываний.)
Почему: Теоретически, представление ловушек может использоваться в качестве средства отладки. Например, реализация может объявить, что 0xDDDD
является представлением ловушек для типов указателей, а затем выбрать инициализацию всех неинициализированных указателей в противном случае для этого битового шаблона. Чтение этого шаблона битов может вызвать ловушку, которая предупреждает программиста об использовании неинициализированного указателя. (Без ловушки, cra sh может не произойти до тех пор, пока не усложнит процесс отладки. Иногда раннее обнаружение является ключевым.) В любом случае представление ловушки требует какой-то ловушки, чтобы служить цели. Реализация не будет определять представление ловушек, не определяя также его ловушку.
Моя точка зрения заключается в том, что представления ловушек должны быть указаны. Они намеренно удаляются из набора значений данного типа. Они не просто «все остальное».
Значения указателя
C ++ 17 §6.9.2 / 3 [basi c .compound]
В этом разделе определяется недопустимое значение указателя. В нем говорится «Каждое значение типа указателя является одним из следующих» перед перечислением четырех возможностей. Это означает, что если у вас есть значение указателя, то это одна из четырех возможностей. Первые три полностью определены (указатель на объект или функцию, указатель за концом и нулевой указатель). Последняя возможность (неверное значение указателя) в другом месте не указана полностью, поэтому она становится универсальной записью «все остальное» в списке (она является «подстановочным знаком», чтобы заимствовать терминологию из комментариев ). Следовательно, этот раздел определяет «недопустимое значение указателя», чтобы обозначить значение указателя, которое не указывает на что-то, не указывает на конец чего-либо и не является нулевым. Если у вас есть значение указателя, которое не соответствует ни одной из этих трех категорий, оно недопустимо.
В частности, если мы согласны с тем, что reinterpret_cast<int*>(42)
не указывает на что-то, не указывает на конец чего-либо и не является нулевым, то мы должны заключить, что это недопустимое значение указателя. (Правда, можно предположить, что результатом приведения является представление ловушки для указателей в некоторой реализации. В этом случае, да, оно не вписывается в список возможных значений указателя, потому что это не было бы значением указателя, следовательно, это представление ловушек. Однако это циклическая логика c. Кроме того, основываясь на N2091 , немногие реализации определяют какие-либо представления ловушек для указателей, поэтому предположение, скорее всего, необоснованно.)
[Примечание: [...] значение указателя становится недействительным, когда хранилище, которое он обозначает, достигает конца своего срока хранения; см. [basi c .stc]. - конец примечания]
Сначала я должен подтвердить, что это примечание. Это объясняет и разъясняет без добавления нового вещества. Не следует ожидать никаких определений в заметке.
В этой заметке приведен пример неверного значения указателя. В нем поясняется, что указатель может (возможно, удивительно) измениться с «точек на объект» на «недопустимое значение указателя» без изменения его значения. Если посмотреть на это с формальной точки зрения логики c, то это примечание подразумевает: "если [что-то], то [неверный указатель]" . Просмотр этого как определения «неверного указателя» является ошибочным ; это всего лишь пример одного из способов получения неверного указателя.
Приведение
C ++ 17 §8.2.10 / 5 [ expr.reinterpret.cast]
Значение целочисленного типа или типа перечисления может быть явно преобразовано в указатель.
Это явно разрешает reinterpret_cast<int*>(42)
. Поэтому поведение определено.
Чтобы быть точным, следует убедиться, что в стандарте нет ничего, что делает 42
"ошибочными данными" до такой степени, что неопределенное поведение является результатом приведения. Остальная часть [§8.2.10 / 5] не делает этого, и:
Стандарт C ++, кажется, не говорит больше о преобразовании целых в указатель.
Это действительный C ++?
Да.