представление ловушки - PullRequest
61 голосов
/ 17 июля 2011
  1. Что такое «представление ловушек» в C (некоторые примеры могут помочь)? Это относится к C ++?

  2. Учитывая этот код ...

    float f=3.5;
    int *pi = (int*)&f;
    

    ... и предполагая, что sizeof(int) == sizeof(float), f и *pi имеют одинаковое двоичное представление / шаблон?

Ответы [ 3 ]

91 голосов
/ 17 июля 2011
  1. Представление ловушки - это универсальный термин, используемый C99 (IIRC не C89) для описания битовых комбинаций, которые вписываются в пространство, занимаемое типом, но запускают неопределенное поведение, если используются в качестве значениятакого типаОпределение дано в разделе 6.2.6.1p5 (с щупальцами во всем 6.2.6), и я не собираюсь его здесь цитировать, потому что оно длинное и запутанное.Тип, для которого существуют такие битовые комбинации, называется «имеющим» представления ловушек.Не требуется, чтобы тип имел какие-либо представления ловушек, но единственный тип, который стандарт гарантирует, что не имеет представления ловушек, это unsigned char (6.2.6.1p5, 6.2.6.2p1).

    Стандарт дает два гипотетических примера представлений ловушек, ни один из которых не соответствует чему-либо, что какой-либо реальный процессор делал в течение многих лет, поэтому я не собираюсь вас с ними путать. хороший пример представления прерываний (также вещь only , которая квалифицируется как представление прерываний аппаратного уровня на любом процессоре, с которым вы, вероятно, столкнетесь) - это сигнальный NaN в плавающемтип точки.Приложение F C99 (раздел 2.1) явно оставляет поведение сигнальных NaN неопределенным, даже несмотря на то, что МЭК 60559 подробно описывает их поведение.

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

  2. Код, который вы показываете, имеет неопределенное поведение, но это из-за правил наложения указателей, а не из-за представлений ловушек.Вот как конвертировать 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 может включать в себя технические corrigienda - я помню, что это было неопределенным в исходной публикации, но было изменено на неопределенное в TC.)

7 голосов
/ 17 июля 2011

Неопределенное поведение для псевдонима с плавающей точкой с указателем на int.

3 голосов
/ 18 июля 2011

Как правило, любое значение с плавающей запятой IEEE-754 без прерывания может быть представлено в виде целого числа на некоторых платформах без каких-либо проблем. Однако существуют значения с плавающей запятой, которые могут привести к неожиданному поведению, если вы предположите, что все значения с плавающей запятой имеют уникальное целочисленное представление и , в результате которого вы заставляете FPU загрузить это значение.

(Пример взят из http://www.dmh2000.com/cpp/dswap.shtml)

Например, при работе с данными FP вам нужно выполнить маршалинг между процессорами с различным порядком байтов, вы можете подумать о следующем:

double swap(double)

К сожалению, если компилятор загружает ввод в регистр FPU, и это представление прерываний, FPU может записать его обратно с эквивалентным представлением прерываний, которое оказывается другим битовым представлением.

Другими словами, есть некоторые значения FP, которые не имеют соответствующего битового представления, если вы не конвертируете правильно (под правильным я подразумеваю через union, memcpy через char * или другой стандартный механизм) .

...