Почему сумма int и float int?

Рассмотрим следующий код:

float d  = 3.14f;
int   i  = 1;
auto sum = d + i;

Согласно cppreference.com, i следует преобразовать в float, когда он добавлен в d. Однако, когда я действительно запускаю код, я считаю, что sum равно 4. Почему это происходит?

Интересно, что когда я явно помещал свой компилятор в режим C11, я обнаружил, что sum равен 4.14. Какие правила изменяет стандарт C11, влияющий на результат?

Что произойдет, если я скомпилировал тот же код с помощью компилятора С++?

Ответ 1

В C (и С++) 3.14f + 1 является типом float из-за продвижения типа int до float.

Но в C, вплоть до C90, и такой стандарт вполне может быть вашим компилятором C по умолчанию, ему присваивается тип int, дающий 4, поскольку int это тип по умолчанию для переменной с автоматическим временем хранения. Начиная с C99, компиляция завершится неудачей, так как неявный int был отозван, хотя компиляторы могут все же разрешить это с предупреждением.

(В С++ 11 и более поздних версиях auto инструктирует компилятор вывести тип. sum будет float со значением 3.14f + 1. Компиляция как С++ 98 или С++ 03 может все еще работают, но генерируют предупреждение о расширениях С++ 11. Это то, что clang делает, например. Это переопределение auto в С++ 11 представляет собой другое расхождение материала между C и С++.)

Ответ 2

Это довольно просто.

В старых версиях C (до C99) вы можете написать что-то вроде

auto n = 3;

и n будет иметь тип int со значением 3. Вы также можете написать

auto n = 3.14f;

и n все равно будет int, со значением 3.

Это называлось неявным int, а K и R сделали его довольно известным.

Итак, вы можете видеть, что

auto sum = d + i;

просто присваивает float type d + i sum, который является неявным int.

Следовательно, ответ 4.

В новых версиях C (C99 и далее) неявный int был удален.

Ответ 3

В некоторых компиляторах файлы с расширением .c скомпилированы как C, а не С++.

float d = 3.14f;
int i = 1;
auto sum = d + i;

скомпилирован как:

float d = 3.14f;
int i = 1;
int sum = d + i;

В языке C auto - это ключевое слово для указания продолжительности хранения. Когда вы создаете переменную auto, она имеет "автоматическую продолжительность хранения". Мы называем эти объекты "локальными переменными". В C все переменные в функциях по умолчанию являются локальными. Вот почему ключевое слово auto вряд ли когда-либо используется.

Ключевое слово auto бесполезно на языке C. Это происходит потому, что перед языком C существовал язык B, в котором это ключевое слово было необходимо для объявления локальных переменных. (B был разработан в NB, который стал C.)