Каково поведение при преобразовании отрицательного значения с плавающей запятой в unsigned int?
Что произойдет, если отрицательное значение с плавающей запятой преобразуется в значение беззнакового целочисленного типа? Стандартные котировки будут оценены. Проблема, с которой я столкнулась, заключается в преобразовании в значения неподписанных интегральных типов из вариантаного класса, который содержит объект типа с плавающей запятой.
Пример:
unsigned i = -.1;
Ответы
Ответ 1
В случае, если отрицательное значение равно -1,0 или ниже, оно вызывает поведение undefined, так как интегральная часть не может быть представлена беззнаковым числом. В противном случае (как в случае -0.1), если он может быть представлен целым типом, это четко определенное поведение. См. Стандарт C11, ISO 9899: 2011:
6.3.1.4
Когда конечное значение реального плавающего типа преобразуется в целое число типа, отличного от _Bool, дробная часть отбрасывается (т.е. значение усекается к нулю). Если значение интегральной части не может быть представлен целым типом, поведение undefined. 61)
И тогда есть ненормативная нотная нота, поясняющая приведенный выше текст:
61) Операция останова, выполняемая, когда значение целочисленного типа преобразуется в неподписанный тип, не нужно выполнять, когда значение реальный плавающий тип преобразуется в неподписанный тип. Таким образом, диапазон переносные реальные значения плавающего значения (-1, Utype_MAX + 1).
ISO/IEC 9899: 1999 (C99) содержит точно такой же текст.
Ответ 2
Это поведение undefined в C99, если число с плавающей запятой меньше или равно -1.0. Если он находится в диапазоне (-1,0, 0,0), результирующее значение будет равно 0.
Из C99, §6.3.1.4, пункт 1
Когда конечное значение реального плавающего типа преобразуется в целочисленный тип, отличный от _Bool, дробная часть отбрасывается (т.е. значение усекается к нулю). Если значение целой части не может быть представлено целым типом, то поведение undefined
Сноска 50 разъясняет поведение для диапазона (-1.0, 0.0).
Ответ 3
В вашем примере unsigned i = -.1;
четко определен как C11, так и C99, а результат i == 0
.
Цитата из N1570, 6.3.1.4 Реальное плавающее и целое число:
- Когда конечное значение реального плавающего типа преобразуется в целочисленный тип, отличный от _Bool, дробная часть отбрасывается (т.е. значение усекается к нулю). Если значение интегральной части не может быть представлен целым типом, поведение undefined 0,61)
61) Операция останова, выполняемая, когда значение целого тип преобразуется в неподписанный тип, не нужно выполнять, когда значение реального плавающего типа преобразуется в неподписанный тип. Таким образом, диапазон (-1, Utype_MAX + 1).
Цитата из N869, 6.3.1.4 Реальные плавающие и целочисленные:
# 1
Когда конечное значение реального плавающего типа преобразуется в целое число типа, отличного от _Bool, дробная часть отбрасывается (т.е. значение усекается к нулю). Если значение интегральной части не может быть представлен целым типом, поведение undefined 0,43)
43) Операция останова, выполняемая, когда значение целого тип преобразуется в неподписанный тип, не нужно выполнять, когда значение реального плавающего типа преобразуется в неподписанный тип. Таким образом, диапазон (-1, Utype_MAX + 1).
Однако, как вы можете видеть из цитат, попытка конвертировать константы с плавающей запятой вне диапазона (-1, Utype_MAX + 1) вызывает поведение undefined.