Почему printf неявное преобразование с плавающей точкой в ​​int не работает? - PullRequest
1 голос
/ 19 декабря 2011

Пожалуйста, помогите мне понять следующий вывод C:

#include<stdio.h>
int main() {
    float x = 4.0;
    printf("%f\n",x);
    printf("%d\n",x);
    int y=x;
    printf("%d\n",y);
    return 0;
}

Выход на компилятор gcc

4.000000
0
4

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

Почему этого не происходит в этом случае?

Ответы [ 3 ]

9 голосов
/ 19 декабря 2011

Вы не печатаете y, вы печатаете x снова.

В качестве примечания, printf не может выполнять преобразования . Поэтому передача значения типа float, когда ожидается %d, является неопределенным поведением.

1 голос
/ 19 декабря 2011

floats автоматически повышаются до doubles, когда передаются как ... параметры (аналогично тому, как chars и short ints повышаются до ints). Когда printf() просматривает спецификатор формата (%d или %f или что-то еще), он захватывает и интерпретирует необработанные данные, которые он получил, в соответствии со спецификатором формата (как int или double или что-то еще), а затем печатает его.

printf("%d\n",x) неправильно, потому что вы передаете double на printf(), но лгите ему, что это будет int. printf() заставляет вас платить за ложь. Он берет 4 байта (скорее всего, но не обязательно 4 байта) из своих параметров, который имеет размер int, он захватывает те байты, откуда вы ранее положили 8 байтов (опять же, скорее всего, но не обязательно 8) байт) из double 4.0, из которых эти 4 байта оказываются всеми нулями, а затем он интерпретирует их как целое число и печатает его. Действительно, степени 2 в формате двойной точности IEEE-754 обычно имеют 52 нулевых бита или более 6 8-битных байтов, равных нулю.

Эти слова «скорее всего, но не обязательно» означают, что стандарт C не требует фиксированного размера и диапазона для типов, и они могут варьироваться от компилятора к компилятору, от ОС к ОС. В наши дни наиболее распространены 4-байтовые ints и 8-байтовые doubles (если мы рассмотрим, например, платформу x86).

1 голос
/ 19 декабря 2011

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

Оператор верен, но дляДля этого преобразования необходимо cast переменную, которую вы хотите преобразовать, а не просто присвоить ее другой переменной int.

Это также вызывает проблемы в операторе printf, так как вы печатаетепеременная типа float с указателем int %d без приведения.

Исправьте ваш код следующим образом:

printf("%d\n", (int) x);
                 ^
                 | this is the cast operation

, и он будет правильно печатать целочисленное значение 4 для переменной * 1018. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...