Семантическое выражение в C - PullRequest
3 голосов
/ 18 июня 2019

Меня смутила следующая формулировка в Стандарте 6.5.4 / 6:

Если значение выражения представлено с большим диапазоном или точность, чем требуется для типа, названного приведением (6.3.1.8), то приведение определяет преобразование, даже если тип выражения совпадает с именованным типом и удаляет любой дополнительный диапазон и точность.

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

Можете ли вы привести пример, демонстрирующий правило? На данный момент это выглядит немного запутанно.

1 Ответ

3 голосов
/ 18 июня 2019

Стандарт позволяет вычислять числа с плавающей точкой с большей точностью, чем тип выражения;например:

float f = 1.234f * 5.678f;

Компилятору разрешено преобразовывать операнды в long double, выполнять умножение, а затем преобразовывать обратно в float.Основанием для этого является то, что на многих процессорах быстрее просто использовать определенный размер регистра с плавающей запятой для вычислений, и обычно люди не заботятся о получении точности.

Это указано в C17 5.2.4.2.2 / 9:

За исключением присваивания и приведения (которые удаляют весь дополнительный диапазон и точность), значения, получаемые операторами с плавающей точкойОперанды и значения, подверженные обычным арифметическим преобразованиям и плавающим константам, оцениваются в формате, диапазон и точность которого могут быть больше, чем требуется типом.Использование форматов оценки характеризуется значением, определяемым реализацией FLT_EVAL_METHOD:

  • −1 не определимо;
  • 0 оценивает все операции и константы только для диапазонаи точность типа;
  • 1 оценивают операции и константы типа float и double для диапазона и точности типа double, оценивают длинные двойные операции и константы для диапазона и точности типа long double;
  • 2 вычисляет все операции и константы для диапазона и точности типа long double.

Все остальные отрицательные значения для FLT_EVAL_METHOD характеризуют поведение, определяемое реализацией.

Таким образом, вы можете проверить FLT_EVAL_METHOD, чтобы выяснить, может ли компилятор сделать это, но вы не можете самостоятельно контролировать настройку.


Текст, который вы цитируете,подтверждая, что оператор приведения преобразует результат обратно в тип приведения, например:

float f = 1.234f * 5.678f + 9.012f;

теоретически может дать болееТочный результат, чем:

float f = (float)(1.234f * 5.678f) + 9.012f;
...