2012-06-22 4 views
1

При использовании printf с% d в качестве спецификатора формата и дающего поплавок в качестве аргумента, например, 2.345, он печатает 1546188227. Итак, я понимаю, что это может быть связано с преобразованием формата точности с плавающей точкой простой десятичный формат. Но когда мы печатаем 2.000 с спецификатором формата% d, то почему он печатает только 0? Пожалуйста, помогите.Озабочен о выходе printf

+1

Опубликовать источник фактической информации. Похоже, ваш код может иметь аргументы, испорченные в 'printf'. Также обратите внимание, что '% d' предназначен для печати целых чисел; '% f' - это то, что вы хотите для поплавков. – dirkgently

ответ

4

Спецификатор формата %d может использоваться только со значениями int (и совместимыми типами). Попытка использовать %d с float или любыми другими типами создает неопределенное поведение. Это единственное объяснение, которое действительно применимо здесь. С точки зрения языка вывод, который вы видите, по сути, является случайным. И вы не гарантируете получение каких-либо результатов вообще.

Если вы по-прежнему заинтересованы в расследовании конкретной причины для вывода, который вы видите (хотя и мало смысла, который он делает), вам придется выполнить исследование, основанное на платформе, потому что фактическое поведение сильно зависит от различных деталей реализации. И вы даже не упоминаете свою платформу в своем посте.

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

+0

Но, хотя это неопределенное поведение, он объясняет вывод. 32 бита младшего порядка мантиссы 'double' 2.345 -' 0x5c28f5c3 = 1546188227', а младшие 32 бита мантиссы 'double' 2.0 - все 0. Таким образом,' printf' просто интерпретирует четыре байта 'double' как' int', а платформа малозначна, поэтому четыре байта представляют собой младшие 32 бита мантиссы. –

0

Если вы пытаетесь сделать его печать целые значения, отливать поплавки Интс в вызове:

printf("ints: %d %d", (int) 2.345, (int) 2.000); 

В противном случае, используйте идентификатор формата с плавающей точкой:

printf("floats: %f %f", 2.345, 2.000); 
0

Когда ты используйте printf с неправильным спецификатором формата для соответствующего аргумента, результатом является неопределенное поведение. Это может быть что угодно и может отличаться от одной реализации к другой. Только правильное использование указанного формата определяет поведение.

0

Сначала маленькая ниттика: буква 2.345 фактически имеет тип double, а не float, и, кроме того, даже float, такой как буквальный 2.345f, будет преобразован в double при использовании в качестве аргумента функции, которая принимает переменное количество аргументов, например printf.

Но здесь случается, что (обычно) 64 бита двойного значения отправляются на printf, а затем он интерпретирует (обычно) 32 этих битов как целочисленное значение. Так получилось, что эти биты были равны нулю.

Согласно стандарту, это то, что называется неопределенным поведением: компилятору разрешено вообще что-либо делать.

1

Перейти here, введите 2.345, нажмите «закругленный». Соблюдайте 64-битное шестнадцатеричное значение: 4002C28F5C28F5C3. Обратите внимание, что 1546188227 является 0x5c28f5c3.

Теперь повторите для 2.00. Обратите внимание, что 64-разрядное шестнадцатеричное значение 4000000000000000

P.S. Когда вы говорите, что вы даете аргумент float, то вы, по-видимому, имеете в виду, что вы даете аргумент double.

1

Здесь какой стандарт ISO/IEC 9899: 1999 $ 7.19.6 состояний:

If a conversion specification is invalid, the behavior is undefined.239) 
If any argument is not the correct type for the corresponding conversion 
specification, the behavior is undefined. 
Смежные вопросы