Глядя на странице человека для printf(3)
в системе FreeBSD (которая является POSIX, кстати), я получаю следующее:
Следующая Модификатор длина действительна для a
, A
, e
, E
, f
, F
, g
, или G
преобразование:
Modifier a, A, e, E, f, F, g, G
l (ell) double (ignored, same behavior as without it)
L long double
Я использовал преобразования с 32-битным типом данных с плавающей запятой. Но проблема здесь в том, что причина в том, что разные форматы float имеют разные размеры, а функция printf
должна знать, какая из них есть, поэтому она может правильно выполнить это преобразование. Использование %Lf
в поплавке может привести к ошибке сегментации, потому что преобразование осуществляет доступ к данным за пределами переменной, поэтому вы получаете неопределенное поведение.
- поплавок: 32-битный
- дважды: 64-битный
- длинный двойной: 80-разрядное
Теперь для long double
, фактический размер определяется платформой и реализации , 80 бит - 10 байтов, но это точно не подходит для 32-битного выравнивания без заполнения. Таким образом, большинство реализаций используют либо 96-битные, либо 128-битные (12 байт или 16 байт соответственно) для установки выравнивания.
Будьте осторожны, однако, потому что это может занять 128 бит, это не означает, что это __float128
(при использовании gcc или clang). Существует хотя бы одна платформа, где указание long double
означает __float128
(SunOS, я думаю), но оно реализовано в программном обеспечении и работает медленно. Кроме того, некоторые компиляторы (Microsoft и Intel приходят на ум) = double
, если вы не указали переключатель в командной строке.
Итак, вы спрашиваете, почему вы получаете предупреждение о компиляторе, если используете неправильный спецификатор? Пожалуйста, откиньтесь назад и снова прочитайте свой вопрос. Затем получите C-книгу и начните учиться с самой первой страницы. – Olaf
@Olaf Это на самом деле запутанная тема для изучения, потому что '% f' означает разные вещи в' printf' vs 'scanf'. – dasblinkenlight
@dasblinkenlight: И в моих собственных функциях это может означать нечто большее. Во всяком случае, речь идет о 'long double', где нет разницы. 'printf' acception' double' для '% f' является просто наследием и просто потому, что вы не можете передать параметр' float' в переменную функцию. Имо это прямо. Просто используйте '% f' для аргументов' float', '% lf' для' double' в обеих функциях ('logn double' уже ясно). Мне это не очень смущает. – Olaf