представление ловушки


  1. что такое представление ловушки в C (некоторые примеры могут помочь)? Это относится к C++?

    float f=3.5;
    int *pi = (int*)&f;
    
  2. Edit: я знаю, что " pi " нарушает правило псевдонимов, и это UB в соответствии со стандартом C. По крайней мере, на GCC он не выдает ошибок, но предупреждает. В этой реализации (т. е. GCC), предполагая sizeof(int) == sizeof(float) do f и *pi имеют одинаковое двоичное представление/шаблон? А как насчет MSVC?
3 58

3 ответа:

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

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

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

  2. код, который вы показываете, не определен поведение, но это происходит из-за правил сглаживания указателя, а не из-за представлений trap. Это как преобразовать float на int С тем же представлением (предполагая, как вы говорите, sizeof(float) == sizeof(int))

    int extract_int(float f)
    {
        union { int i; float f; } u;
        u.f = f;
        return u.i;
    }
    

    этот код нет данных (не неопределенное) поведение в C99, что в основном означает, что стандарт не определяет какое целое значение производится, но вы получаете некоторые действительное целочисленное значение, это не ловушка представление, и компилятор не может оптимизировать в предположении, что вы этого не сделали. (Раздел 6.2.6.1, пункт 7. Моя копия C99 может включать технические исправления - мое воспоминание заключается в том, что это был не определено в исходной публикации, но было изменено на unspecified в TC.)

неопределенное поведение для псевдонима поплавка с указателем на int.

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

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

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

double swap(double)

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

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