Почему преобразование «целого числа вне диапазона в целое» приводит к IB, а преобразование «целого числа вне диапазона в целое» приводит к UB?

Последующий вопрос для:

  1. Преобразование типов: двойное в char: несколько вопросов
  2. Назначение беззнакового значения знаковому символу

Контекст: рабочий проект ISO / IEC 9899: 202x (E) — 5 февраля 2020 г. C17..C2x N2479 (курсив добавлен):

J.3 Поведение, определяемое реализацией, J.3.5 Целые числа

— Результат или сигнал, вызванный преобразованием целого числа в целочисленный тип со знаком, когда значение не может быть представлено в объекте этого типа (6.3.1.3).

6.3.1.4 Действительное число с плавающей запятой и целое число

Когда конечное значение стандартного плавающего типа преобразуется в целочисленный тип, отличный от _Bool, дробная часть отбрасывается (т. Е. Значение обрезается до нуля). Если значение составной части не может быть представлено целочисленным типом, поведение не определено.

Вопрос: Почему преобразование «целого числа вне диапазона в целое» приводит к IB, а преобразование «целого числа вне диапазона в целое» приводит к UB? Т.е. почему поведение непоследовательно (например, IB в обоих случаях)?

UPD. Ответ пользователя P.P. в дублируется вопрос:

Я сомневаюсь, что за это можно ответить. Это в основном из-за истории и на основе реализаций, поведения оборудования и т. Д., Когда C. был стандартизован. Таким образом, согласованность была невозможной / практичной (это не похоже на то, что комитет решил произвольно классифицировать определенное поведение как IB, UB или неопределенное).

Определяемое реализацией поведение не ограничивается стандартом, но каждая реализация должна предоставлять документацию о том, что происходит на этой конкретной платформе. Это конкретное правило даже явно указывает, что многие реализации будут вызывать сигнал. Это сильно отличается от заданного реализацией result или value, в которых стандарт по-прежнему полностью определяет все побочные эффекты, и только результирующее значение может отличаться. Неопределенное поведение не ограничивается стандартом, и также нет требований к документации.   —  person pmor    schedule 11.03.2021

См. также:  присвоение значения индексу массива возвращает SIGSEGV; ошибка сегментации. | c

Unspecified (result / value) — это не требующий документации аналог для результата / значения, определенного реализацией.   —  person pmor    schedule 11.03.2021

@BenVoigt, Как stackoverflow.com/questions/ 2397984 / отвечает на вопрос? Вопрос не в определении IB / UB. Речь идет об отсутствии согласованности: IB в случае «вне диапазона целого числа в целое», UB в случае выхода из диапазона с плавающей запятой в целое число ».   —  person pmor    schedule 11.03.2021

Согласен, проголосовали за повторное открытие.   —  person pmor    schedule 14.03.2021

@BenVoigt: В C89 поведение было определено для всех реализаций без битов заполнения или представлений ловушек, но определенное поведение не обязательно было разумным в реализациях с дополнением до единиц или знаковой величиной. C99 перехарактеризовал его и добавил положение, отсутствующее в C89, позволяющее реализациям подавать сигнал, но на практике почти ни одна реализация не пользуется свободой подавать сигнал.   —  person pmor    schedule 15.03.2021

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. pmor

    С точки зрения Стандарта, вопрос о том, следует ли классифицировать что-либо как поведение, определяемое реализацией и неопределенное поведение, зависит от того, должны ли все реализации требоваться для документирования поведения, в целом совместимого с семантикой языка, независимо от стоимости или полезности. . Не было необходимости предписывать, чтобы реализации обрабатывали действия способами, которые их клиенты сочли бы полезными, потому что ожидалось, что реализации, которым разрешено вести себя таким образом, будут делать это с мандатом или без него. Следовательно, было сочтено, что лучше характеризовать полезные действия Undefined Behavior, реализации которых могут обрабатывать 100% согласованно, чем характеризовать как действия, определяемые реализацией, которые иногда могут быть непрактичными для последовательной реализации.

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

    int f1(int x, int y);
    int f2(int x, int y, int z);
    void test(int x, unsigned char y)
    {
      short temp = x/(y+1);
      if (f1(x,y))
        f2(x,y,temp);
    }
    

    На платформах, где преобразование в краткое всегда будет выполняться без побочных эффектов, или в реализациях, которым разрешено обрабатывать преобразования за пределами допустимого диапазона как неопределенное поведение, вычисление x / (y + 1) и преобразование в краткое можно отложить до тех пор, пока после вызова f1 и вообще пропускается, если f1 возвращает ноль. Однако такое преобразование может повлиять на поведение сигнала, вызванного преобразованием, и, таким образом, не представляется допустимым в соответствии со Стандартом для реализаций, где преобразование может вызвать сигнал.

    С другой стороны, хотя может быть полезно, чтобы реализации генерировали сигнал в случае преобразования за границы, такие сигналы в основном были бы полезны в ситуациях, когда качество диагностики считалось более важным, чем производительность. Реализации, в которых производительность была более важной, могли бы свободно выполнять оптимизацию, подобную приведенной выше, если бы они обрабатывали преобразование как не имеющее побочных эффектов, и казалось вероятным, что последний способ действий будет практичным на всех платформах.

    Были платформы, на которых самый быстрый способ преобразования float в int остановится; как уже отмечалось, возможность того, что действие может перехватить, сделает классификацию поведения, определяемого реализацией, дорогостоящим. Хотя маловероятно, что были бы какие-либо платформы, на которых было бы непрактично обрабатывать преобразование, например float в short как преобразование из float в int, за которым следует преобразование из int в short, есть платформы, где это может быть не самым полезным поведением (например, если платформа может без дополнительных затрат привязать результат такого преобразования к диапазон целевого типа, который может быть более полезным, чем преобразование в int, а затем в целевой тип). Даже если бы авторы Стандарта ожидали и предполагали, что преобразование типов с плавающей запятой в малые целочисленные типы никогда не приведет к неупорядоченным ловушкам для любых значений, находящихся в диапазоне int, Стандарт классифицирует как общие действия UB, которые могут вести себя непредсказуемо в некоторых случаях. случаев, но предсказуемым, зависящим от реализации способом в других, без каких-либо усилий по выявлению конкретных случаев, в которых они должны вести себя предсказуемо.

    Последний принцип, возможно, лучше всего проиллюстрирован, исследуя способ описания сдвига влево в C89 и C99. Нет причин, по которым x << 0 не должен давать x для всех целочисленных значений x, и способ, которым C89 определил поведение, будет делать именно это. Однако спецификация C89 определяет поведение в некоторых случаях, когда может быть полезно разрешить некоторым реализациям вести себя другим и не обязательно предсказуемым образом. C99 не предпринимает никаких усилий для выявления ситуаций, когда все реализации должны обрабатывать сдвиг отрицательных чисел влево так же, как это делал C89, потому что авторы ожидали, что все реализации будут обрабатывать такие случаи в стиле C89 с мандатом или без него.

    деление на ноль — ›Как int x, unsigned char y, ... x/(y+1) понесет деление на 0? (Разве мы не должны предполагать UCHAX_MAX < INT_MAX?) person pmor; 21.03.2021

    @ chux-ReinstateMonica: значение x/(y+1) может выходить за пределы диапазона значений short, вызывая появление сигнала, когда оно назначается temp. Семантика сигналов такова, что любые побочные эффекты от сигнала, вызванного таким назначением, должны предшествовать любым побочным эффектам от вызова f1(). Если, например, f1() должен был изменить обработчик сигнала для преобразований, выходящих за границы, что могло произвольно изменить поведение отказа преобразования, если преобразование было отложено до тех пор, пока не будет возвращено f1. Обратите внимание, что хотя код может определить, возникнет ли сигнал … person pmor; 22.03.2021

    … дешевле, чем это могло бы выполнить деление (например, проверяя, является ли x положительным или отрицательным, а затем (при необходимости) гарантируя, что оно меньше 32768*i или больше -32769*i, стоимость выполнения этого вычисления и затем, возможно, имея выполнение разделения также, вероятно, превысит затраты на простое выполнение разделения без каких-либо условий. person pmor; 22.03.2021

    Моя цель с использованием деления, как я это сделал, заключалась в том, чтобы получить вычисления, свободные от побочных эффектов, результат которых можно было бы легко показать, что он попадает в диапазон int, но нелегко показать, что он попадает в диапазон short. person pmor; 22.03.2021

    Спасибо за подробности. person pmor; 22.03.2021

    @ chux-ReinstateMonica: Я только что вычитал свой пост и увидел, что в нем есть избыточное упоминание о делении на ноль, хотя я переработал код, чтобы гарантировать, что единственная часть вычислений, которая может уловить, — это преобразование из int в short. person pmor; 22.03.2021

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: