Ответ 1
-
Представление ловушки - это общий термин, используемый C99 (IIRC не C89) для описания битовых шаблонов, которые вписываются в пространство, занимаемое типом, но запускают поведение undefined, если оно используется как значение этот тип. Это определение содержится в разделе 6.2.6.1p5 (с щупальцами во всех 6.2.6), и я не буду приводить его здесь, потому что он длинный и запутанный. Тип, для которого существуют такие битовые шаблоны, называется "иметь" ловушечные представления. Для наличия каких-либо ловушечных представлений не требуется тип, но единственным типом, который стандартные гарантии не будут иметь ловушечных представлений, является
unsigned char
(6.2.6.1p5, 6.2.6.2p1).Стандарт дает два гипотетических примера ловушечных представлений, ни один из которых не соответствует чему-либо, что какой-либо реальный процессор выполнял в течение многих лет, поэтому я не собираюсь смущать вас с ними. Хорошим примером представления ловушки (также единственное, что квалифицируется как представление ловушки аппаратного уровня на любом CPU, с которым вы, вероятно, столкнетесь) является сигнальным NaN в типе с плавающей точкой. C99 Приложение F (раздел 2.1) явно оставляет поведение сигнальных NaNs undefined, хотя IEC 60559 подробно описывает их поведение.
Стоит отметить, что, хотя типам указателей разрешено иметь ловушечные представления, нулевые указатели не являются ловушками. Нулевые указатели вызывают поведение undefined, если они разыменованы или смещены; другие операции над ними (что наиболее важно, сравнения и копии) четко определены. Представления Trap вызывают поведение undefined, если вы просто читаете их, используя тип, который имеет представление ловушки. (Неверные, но не нулевые указатели являются или должны рассматриваться как ловушечные представления, являются предметом обсуждения. ЦП не относится к ним таким образом, но компилятор может.)
-
Код, который вы показываете, имеет поведение undefined, но это из-за правил сглаживания указателей, а не из-за ловушек. Вот как преобразовать a
float
вint
с тем же представлением (предполагая, как вы говорите,sizeof(float) == sizeof(int)
)int extract_int(float f) { union { int i; float f; } u; u.f = f; return u.i; }
Этот код имеет неуказанное поведение (не undefined) в C99, что в основном означает, что стандарт не определяет, какое целочисленное значение создается, но вы получаете некоторое действительное целочисленное значение, это не представление ловушки, а компилятор не разрешается оптимизировать, исходя из предположения, что вы этого не сделали. (Раздел 6.2.6.1, параграф 7. Моя копия C99 может включать технические корректуры - мое воспоминание состоит в том, что это было undefined в оригинальной публикации, но было изменено на неуказанное в TC.)