почему результат (double + int) равен 0 (язык C) - PullRequest
0 голосов
/ 31 января 2019

результат

printf("%d\n", 5.0 + 2);

равен 0

, но

int num = 5.0 + 2;
printf("%d\n", num);

равен 7

В чем разница междудва?

Ответы [ 5 ]

0 голосов
/ 31 января 2019

Обычные арифметические преобразования неявно выполняются для приведения их значений к общему типу.Компилятор сначала выполняет целочисленное продвижение;если операнды по-прежнему имеют разные типы, то они преобразуются в тип, который отображается наивысшим в следующей иерархии -

enter image description here

В int num = 5.0 + 2; этот кодфрагмент вы добавляете число с плавающей точкой с целым числом и снова сохраняете обратно в целое число.Таким образом, c автоматически преобразует результат в целое число для хранения в переменной целочисленного типа.Таким образом, при печати с использованием% d печатается нормально.

Но в printf("%d\n", 5.0 + 2); этом фрагменте кода добавление преобразуется в число с плавающей запятой, так как число с плавающей запятой имеет более высокий приоритет над целым числом, но вы печатаете его, используя% d.Здесь несоответствие спецификатора формата вызывает неожиданный результат.

0 голосов
/ 31 января 2019

5.0+2 набрано double.

Предупреждение компилятора для

int main() { return _Generic(5.0 + 2, struct foo: 0); }

должно сообщить вам столько же, если

int main() { return _Generic(5.0 + 2, double: 5.0+2); }

компиляция без ошибки не't.

Сопоставление "%d" с double в printf приводит к неопределенному поведению.

Любой результат является законным, включая удаление жесткого диска (маловероятно, если ваша программагде-то уже есть такая функциональность, если она есть, UB может привести к непреднамеренному вызову).

0 голосов
/ 31 января 2019

Во всех выражениях каждый операнд имеет тип.5.0 имеет тип double.2 имеет тип int.

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

. Таким образом, вы передаете double printf, но вы сказали ему ожидать int, так как вы использовали %d.Результатом является ошибка, результат не определен.

Но в случае int num = 5.0 + 2; вы сначала получите результат как double, 7.0.Затем верните преобразование обратно в int.Этот код эквивалентен:

int num = (int)((double)5.0 + (double)2);

Более подробно здесь: Неявные правила продвижения типа

0 голосов
/ 31 января 2019

Результат выражения 5.0 + 2 имеет тип double, так как по крайней мере один из двух операндов оператора + здесь представляет собой значение с плавающей запятой / двойное значение (поэтому другой будет преобразован в doubleперед добавлением).

Если вы напишите printf("%d\n", 5.0 + 2), вы передадите значение с плавающей запятой, где спецификатор формата фактически ожидает int.Это несоответствие является неопределенным поведением, и 0, который вы получите, может быть чем-то другим (другое число, сбой, .... что-нибудь), тоже.

int num = 5.0 + 2, напротив, преобразуетdouble -значение, полученное в результате 5.0 + 2 возврата к целочисленному значению (исключая любую дробную часть).Таким образом, значение num будет 7 и будет, поскольку num является целочисленным типом, действительным в сочетании со спецификатором формата %d затем.

0 голосов
/ 31 января 2019

Результат 5.0 + 2 равен 7.0 и имеет тип double.

Формат "%d" предназначен для печати int.

Несоответствие спецификации формата и аргументатип приводит к неопределенное поведение .

Чтобы напечатать значение float или double с printf, вам следует использовать формат "%f".


С помощью

int num = 5.0 + 2;

вы конвертируете результат 5.0 + 2 в int значение 7.Затем вы печатаете значение int, используя правильный спецификатор формата.

...