преобразование постоянного типа c в арифметике

#c #c 11 #clang #clang-extensions

#c #c 11 #лязг #clang-расширения

Вопрос:

Предыстория

Я пытаюсь изучать C 11 с помощью clang на Mac.

Вопрос

Как сказано в книге, когда тип float соответствует int или нижнему регистру в арифметике, последний будет преобразован в float. Это верно в таких случаях, как:

 cout << 9.0 / 5 << endl;
  

Результат дает 1.8000 , но когда я пытаюсь использовать суффикс, чтобы обеспечить тип для констант, таких как:

 cout << 9.0f / 5i << endl;
  

В результате получается 1 . Интересно, почему? Существуют ли за этим другие правила или механизм?

Комментарии:

1. Как вы вообще смогли его скомпилировать? i не является встроенным числовым суффиксом (в частности, он не означает int , как вы, кажется, полагаете). Для компиляции этого должно быть operator"" i() определено где-то в вашей программе; найдите его, посмотрите, что он делает.

2. 5i является ли мнимое число (т. Е. комплексное число 0 5i) не целым числом 5.

3. @40 два не из коробки. Компилятор не знает, что делать с 5i как сказал Игорь.

4. @tgmath кажется, в Clang v3.4 это не обязательно coliru.stacked-crooked.com/a/60abcb7c6b065585

5. @IgorTandetnik Мне кажется, я неправильно понял «я». Спасибо за это. Но, по правде говоря, у меня нет другого operator"" i() в test.cpp . Я просто включаю iostream и использую строку напрямую.

Ответ №1:

Использование i в качестве суффикса является расширением, которое указывает на мнимую константу в отличие от целого числа, которое также поддерживается gcc . Без предупреждений позволяет clang просто интерпретировать 5i как комплексное число. При включенном предупреждении (конкретно -Wconversion) выдается следующее предупреждение:

 warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]
std::cout << 9.0f / 5i << std::endl;
                    ^

warning: implicit conversion discards imaginary component: '_Complex float' to 'bool' [-Wconversion]
std::cout << 9.0f / 5i << std::endl;
~~~          ~~~~~^~~~
  

Похоже, что для _Complex нет перегрузки, поэтому результат преобразуется в bool. Мы можем увидеть это более четко на следующих примерах:

 float f = (9.0f / 5   0i) ;
std::cout << f << std::endl ;
  

который выводит 1.8 .

Если вам просто нужен литерал int, тогда суффикс не требуется, другие целые суффиксы u, l, ul, ll, ull для unsigned, long, unsigned long, long long and unsigned long long соответственно.

Итак, в вашем случае:

 9.0f / 5
  

было бы то, что вы хотите, если вы хотите застраховать 9.0 , интерпретируется как число с плавающей точкой, иначе оно будет интерпретироваться как double.

5 также будет преобразовано в значение с плавающей точкой, поскольку / оператор будет выполнять обычные арифметические преобразования для своих операндов.