- bullseye-backports 4.17.0-2~bpo11+1
- testing 4.17.0-2
- unstable 4.17.0-2
PRINTF(3) | Руководство программиста Linux | PRINTF(3) |
ИМЯ¶
printf, fprintf, dprintf, sprintf, snprintf, vprintf, vfprintf, vdprintf, vsprintf, vsnprintf - преобразование форматированного вывода
СИНТАКСИС¶
#include <stdio.h>
int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int dprintf(int fd, const char *format, ...); int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...); #include <stdarg.h>
int vprintf(const char *format, va_list ap); int vfprintf(FILE *stream, const char *format, va_list ap); int vdprintf(int fd, const char *format, va_list ap); int vsprintf(char *str, const char *format, va_list ap); int vsnprintf(char *str, size_t size, const char *format, va_list ap);
snprintf(), vsnprintf():
|| /* версии glibc <= 2.19: */ _BSD_SOURCE
dprintf(), vdprintf():
- Начиная с glibc 2.10:
- _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _GNU_SOURCE
ОПИСАНИЕ¶
The functions in the printf() family produce output according to a format as described below. The functions printf() and vprintf() write output to stdout, the standard output stream; fprintf() and vfprintf() write output to the given output stream; sprintf(), snprintf(), vsprintf(), and vsnprintf() write to the character string str.
Функция dprintf() подобна fprintf() за исключением того, что выводит данные в файловый дескриптор fd, а не в поток stdio.
Функции snprintf() и vsnprintf() записывают не более size байт (включая конечный байт null ('\0')) в str.
Функции vprintf(), vfprintf(), vdprintf(), vsprintf(), vsnprintf() эквивалентны printf(), fprintf(), dprintf(), sprintf(), snprintf(), соответственно, за исключением того, что они вызываются с va_list, а не переменным числом аргументов. Эти функции не вызывают макрос va_end. Так как они вызывают макрос va_arg, значение ap не определено после вызова. Смотрите stdarg(3).
Все эти функции выводят данные в соответствии со строкой format, которая определяет, каким образом последующие параметры (или доступные параметры переменной длины из stdarg(3)) преобразуют поток вывода.
В C99 и POSIX.1-2001 указано, что результат не определён, если вызов sprintf(), snprintf(), vsprintf() или vsnprintf() привёл бы копированию между перекрывающимися объектами (например, если массив строк назначения и один из указанных входных аргументов ссылаются на один буфер). Смотрите ЗАМЕЧАНИЯ.
Структура строки формата¶
Строка параметров — это строка символов, начинающаяся и заканчивающаяся в своём начальном состоянии сдвига, если оно есть. Строка может состоять из нуля или более директив: обычных символов (кроме %), которые неизменно копируются в поток выхода; и спецификаторов преобразования, по каждому из которых выбирается ноль или более последующих параметров. Каждый спецификатор преобразований начинается с символа % и заканчивается спецификатором преобразования. Между ними могут находиться (в определённом порядке) ноль или более флагов, необязательная минимальная ширина поля, необязательная точность и необязательный модификатор длины.
Параметры должны точно соответствовать (после преобразования типа) спецификаторам преобразований. По умолчанию параметры используются в порядке поступления, где каждая «*» (смотрите Ширина поля и Точность ниже) и каждый спецификатор преобразования требуют последующего параметра (если указано недостаточно параметров, то это приведёт к ошибке). Возможно явное указание на то, какой параметр будет следующим, с помощью записи «%m$» вместо «%» и «*m$» вместо «*ю, где десятичная цифра m означает позицию нужного параметра в их списке; список начинается с единицы. Таким образом,
printf("%*d", width, num);
и
printf("%2$*1$d", width, num);
означают одно и то же. Вторая форма записи позволяет производить указание на тот же параметр несколько раз. Стандарт C99 не поддерживает использование «$», который пришёл из Single UNIX Specification. Если используется «$», то он должен использоваться для всех преобразований аргументов и во всех аргументах ширины и точности, но он может быть смешан с форматами «%%», которые не поглощают аргументы. Там может не быть пробелов между числами аргументов, обусловленные использованием «$». Например, если аргументы 1 и 3 определены, то аргумент 2 должен также быть определён где-то в строке параметров.
В некоторых цифровых преобразованиях используется символ разделения целой и дробной частей или символ разделения тысяч. Текущий символ зависит от локали, а именно от значения переменной LC_NUMERIC (смотрите setlocale(3)).В локали POSIX по умолчанию используется символ «.» и не отсутствует символ разделения. Таким образом,
printf("%'.2f", 1234567.89);
выводит «1234567.89» при локали POSIX, «1234567,89» при локали nl_NL и «1.234.567,89» при локали da_DK.
Флаги¶
За символом % может быть указано ноль или несколько следующих флагов:
- #
- Значение преобразуется в «альтернативную форму». Для преобразования типа o первый символ выходного потока будет нуль (префикс 0, если до этого его не было указано). Для преобразований типа x и X к ненулевому результату добавляется «0x» (или «0X» для преобразования типа X). При преобразованиях типа a, A, e, E, f, F, g и G результат всегда будет содержать десятичную точку, даже если за ней не следует цифр (обычно десятичная точка присутствует в результате таких преобразований только, если за ними следуют цифры). Для преобразований g и G завершающие нули не удаляются из результата, как это обычно случается. Результат для других преобразований не определён.
- 0
- В значение добавляются нули. При преобразованиях типа d, i, o, u, x, X, a, A, e, E, f, F, g и G преобразуемое значение слева дополняется нулями (вместо пробелов). Если присутствуют флаги 0 и -, то флаг 0 игнорируется. Если в числовом преобразовании указана точность (d, i, o, u, x, и X), то флаг 0 игнорируется. Поведение флага при других преобразованиях не определено.
- -
- Выравнивает результат преобразования по левой границе поля (по умолчанию выравнивание выполняется справа). Преобразованное значение дополняется справа пробелами, а не пробелами или нулями слева. Флаг - отменяет флаг «0», если было указано оба флага.
- ' '
- (пробел). Устанавливает слева перед положительными числами (или пустой строкой) знак пробела при знаковых преобразованиях.
- +
- Знак + или - всегда помещается перед преобразованным числом со знаком. По умолчанию знак используется только для отрицательных чисел. Флаг + отменяет действие пробела, если указаны оба флага.
Пять флагов, описанных выше, определены в стандарте C99. В стандарте Single UNIX Specification определён ещё один дополнительный флаг.
- '
- При десятичных преобразованиях (i, d, u, f, F, g, G) результат группируется символом разделителя тысяч, если информация локализации указывает на это (смотрите setlocale(3)). Заметим, что многие версии gcc(1) не могут распознать этот флаг и выводят соответствующее предупреждение (SUSv2 не содержи %'F, но в SUSv3 его добавили).
В glibc 2.2 добавлен ещё один флаг.
- I
- При преобразовании целых десятичных чисел (i, d, u) в результате используется альтернативное представление цифр согласно локали. Например, начиная с glibc 2.2.3 это даёт арабско-индийские цифры для персидской локали («fa_IR»).
Ширина поля¶
Необязательная строка из десятичных цифр (с первой цифрой, отличной от нуля) определяет минимальную ширину поля. Если преобразованное значение имеет меньшее количество знаков, чем ширина поля, то оно слева дополняется пробелами (или справа, если указан флаг выравнивания по левому краю). Вместо строки десятичных цифр можно указать «*» или «*m$» (для некоторого десятичного числа m), чтобы определить ширину поля по ширине следующего аргумента или аргумента с номером m (должен быть типа int), соответственно. Отрицательная ширина поля принимается как флаг «-», устанавливающий положительную ширину поля. Несуществующая или небольшая ширина поля не делает его усечённым; если результат преобразования больше ширины поля, то поле расширяется, чтобы вместить в себя преобразованное значение.
Точность¶
Необязательный параметр точности в виде знака точки («.») сопровождается необязательной строкой десятичных цифр. Вместо строки десятичных цифр можно указать «*» или «*m$» (для некоторого десятичного числа m), чтобы определить значение точности по следующему аргументу или аргументу с номером m (должен быть типа int), соответственно. Если точность указана как «.», то она обрабатывается как нулевая. Отрицательная точность обрабатывается как если не указывалась совсем. Это позволяет ограничивать количество выводимых символов для преобразований d, i, o, u, x и X; показывать определённое количество цифр после десятичной точки для преобразований a, A, e, E, f и F; показывать максимальное количество значащих цифр для преобразований g и G или максимальное количество символов для печати строк при преобразованиях s и S.
Модификатор длины¶
Устанавливаются для следующих «преобразований целого» d, i, o, u, x или X.
- hh
- Преобразование целого числа соответствует аргументам signed char или unsigned char, а также тип преобразования n соответствует указателю на аргумент signed char.
- h
- A following integer conversion corresponds to a short or unsigned short argument, or a following n conversion corresponds to a pointer to a short argument.
- l
- (ell) A following integer conversion corresponds to a long or unsigned long argument, or a following n conversion corresponds to a pointer to a long argument, or a following c conversion corresponds to a wint_t argument, or a following s conversion corresponds to a pointer to wchar_t argument.
- ll
- (ell-ell). A following integer conversion corresponds to a long long or unsigned long long argument, or a following n conversion corresponds to a pointer to a long long argument.
- q
- Синоним ll. Является нестандартным расширением, унаследовано от BSD; не используйте в новом коде.
- L
- Типы преобразования a, A, e, E, f, F, g или G соответствуют аргументу long double (в C99 допускается %LF, но в SUSv2 нет).
- j
- Преобразование целого числа соответствует аргументам intmax_t или uintmax_t, а также тип преобразования n соответствует указателю на аргумент intmax_t.
- z
- Преобразование целого числа соответствует аргументам size_t или ssize_t, а также тип преобразования n соответствует указателю на аргумент size_t.
- Z
- Нестандартный синоним z, который появился до z. Не используйте в новом коде.
- t
- Преобразование целого числа соответствует аргументам ptrdiff_t или тип преобразования n соответствует указателю на аргумент ptrdiff_t.
В SUSv3 определено всё вышеперечисленное, за исключением указанных как нестандартное расширение. В SUSv2 определены только модификаторы длины h (в hd, hi, ho, hx, hX, hn) и l (в ld, li, lo, lx, lX, ln, lc, ls) и L (в Le, LE, Lf, Lg, LG).
As a nonstandard extension, the GNU implementations treats ll and L as synonyms, so that one can, for example, write llg (as a synonym for the standards-compliant Lg) and Ld (as a synonym for the standards compliant lld). Such usage is nonportable.
Тип преобразования¶
Символы, которые определены как типы преобразования. Типы преобразования и их значения:
- d, i
- Параметр int преобразует символы в их знаковое десятичное отображение. Точность (если указана) задаёт минимальное количество цифр в изображении результата; если результат можно показать с помощью меньшего количества цифр, то слева добавляются незначащие нули. По умолчанию значение точности равно единице. При выводе нуля с нулевой точностью выходной поток будет пуст.
- o, u, x, X
- Параметр unsigned int преобразуется в беззнаковое восьмеричное число (o), беззнаковое десятичное (u) или беззнаковое шестнадцатеричное (x и X). Буквы abcdef используются в преобразованиях x; буквы ABCDEF используются в преобразованиях X. Точность (если указана) задаёт минимальное количество цифр в изображении результата; если результат можно показать с помощью меньшего количества цифр, то слева добавляются незначащие нули. По умолчанию значение точности равно единице. При выводе нуля с нулевой точностью выходной поток будет пуст.
- e, E
- Параметр double округляется и преобразуется в вид [-]d.ddde±dd, в котором есть одна цифра (не равная нулю, если аргумент не равен нулю) до символа десятичной точки и количество цифр после, указывающих на требуемую точность. Если точность отсутствует, она принимается равной 6; если точность равна нулю, десятичная точка не показывается. В преобразовании для представление экспоненты E используется буква E (а не e). В экспоненте всегда не менее двух цифр; если значение ноль, то экспонента выводится как 00.
- f, F
- Параметр double округляется и преобразуется в десятичное выражение в виде [-]ddd.ddd, где количество цифр после десятичной точки указывает на требуемую точность. Если точность отсутствует, она принимается равной 6-и; если точность равна нулю, десятичная точка не показывается. Если десятичная точка есть, перед ней должна быть минимум одна цифра
- (в SUSv2 отсутствует информация о F и указано, что этот символ предназначен для отображения символов бесконечности и NaN. В SUSv3 добавлен тип F. В стандарте C99 определены «[-]inf» или «[-]infinity» для указания бесконечности, и строка начинающаяся с «nan» для NaN в случае, если тип преобразования равен f, а начинающаяся с «[-]INF», «[-]INFINITY» или «NAN» в случае, если тип преобразования равен F).
- g, G
- Параметр double преобразуется в стиле f или e (или F или E, для преобразования G). Точность определяется количеством значащих цифр. Если точность отсутствует, то она определяется равной 6-и цифрам; если точность равна нулю, то она трактуется как 1. Стиль e используется, если экспонента преобразования меньше -4, или больше или равна ей. Завершающие нули удаляются из дробной части результата; десятичная точка стоит, только если за ней следует, по крайней мере, одна цифра.
- a, A
- (C99; not in SUSv2, but added in SUSv3) For a conversion, the double argument is converted to hexadecimal notation (using the letters abcdef) in the style [-]0xh.hhhhp±d; for A conversion the prefix 0X, the letters ABCDEF, and the exponent separator P is used. There is one hexadecimal digit before the decimal point, and the number of digits after it is equal to the precision. The default precision suffices for an exact representation of the value if an exact representation in base 2 exists and otherwise is sufficiently large to distinguish values of type double. The digit before the decimal point is unspecified for nonnormalized numbers, and nonzero but otherwise unspecified for normalized numbers. The exponent always contains at least one digit; if the value is zero, the exponent is 0.
- c
- Если модификатор l не указан, то параметр int преобразуется в unsigned char и выводится как результирующее значение. Если l указан, то параметр wint_t (широкий символ) преобразуется в многобайтовую последовательность вызовом функции wcrtomb(3); первое его значение преобразуется в начальное значение и выводится в виде многобайтовой строки.
- s
- Если модификатор l не указан: параметр const char * преобразуется в указатель на массив символьного типа (строковый указатель). Символы из массива выводятся до конечного байта null ('\0', не включая его); если указана точность, то выводится не более установленного количества символов. Если точность указана, то байт null не нужен. Если точность не указана или она больше, чем размер массива, то массив должен содержать конечный байт null.
- Если модификатор l указан: параметр const wchar_t * должен быть указателем на массив широких символов. Широкие символы из массива преобразуются в многобайтовые символы (каждый вызовом функции wcrtomb(3), при этом первое значение преобразуется в начальное значение первого широкого символа) и так до конечного широкого символа null. Результирующие многобайтовые символы выводятся до конечного байта null (не включая его). Если указана точность, то выводится количество байтов, не превышающее это значение, а оставшаяся часть многобайтовых символов не выводится. Заметим, что точность определяется количеством выведенных байт, не широких символов или положением на экране. Массив должен содержать конечный широкий символ null, если точность не указана, и содержать количество байт, меньше размера массива.
- C
- (отсутствует в C99 или C11, но есть в SUSv2, SUSv3 и SUSv4) Синоним lc. Не используйте.
- S
- (отсутствует в C99 или C11, но есть в SUSv2, SUSv3 и SUSv4) Синоним ls. Не используйте.
- p
- Параметр указателя void *, выводящийся в шестнадцатеричном виде (также как при %#x или %#lx).
- n
- Количество символов, выводящихся в целом типе int * (или других) без преобразующих параметров. Данный параметр должен быть int * или его вариантом, размер которого совпадает с (необязательно) указываемым целым модификатором длины. Параметр не преобразуется (данный тип не поддерживается библиотекой bionic C). Поведение не определено, если тип преобразования содержит флаги, ширину поля или точность.
- m
- (расширение glibc; поддерживается uClibc и musl) Выводит содержимое strerror(errno). Параметр не требуется.
- %
- Выводит символ '%'. Параметр не требуется. Полный спецификатор преобразования — '%%'.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении данные функции возвращают количество напечатанных символов (не включая байт null, используемый в конце выводимых строк).
Функции snprintf() и vsnprintf() записывают не более size байт (включая конечный байт null ('\0')). Если вывод был обрезан из-за данного ограничения, то возвращаемое значение это количество символов (не включая конечный байт null), которое было бы записано в результирующую строку, если бы было достаточно места. Таким образом, если возвращённое значение больше или равно size, то вывод был обрезан (также смотрите ЗАМЕЧАНИЯ ниже).
Если возникла ошибка, то возвращается отрицательное значение.
АТРИБУТЫ¶
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
printf(), fprintf(), sprintf(), snprintf(), vprintf(), vfprintf(), vsprintf(), vsnprintf() | Безвредность в нитях | MT-Safe locale |
СООТВЕТСТВИЕ СТАНДАРТАМ¶
fprintf(), printf(), sprintf(), vprintf(), vfprintf(), vsprintf(): POSIX.1-2001, POSIX.1-2008, C89, C99.
snprintf(), vsnprintf(): POSIX.1-2001, POSIX.1-2008, C99.
Функции dprintf() и vdprintf() изначально являлись расширениями GNU, но позже были стандартизованы в POSIX.1-2008.
Что касается возвращаемого значения snprintf(), то стандарты SUSv2 и C99 противоречат друг другу: когда snprintf() вызывается с size=0, то SUSv2 предусматривает возврат неопределённого значения меньше единицы, а C99 устанавливает в этом случае str равным NULL и возвращает значение (как обычно) в виде количества символов, достаточного для выходной строки. В POSIX.1-2001 и новее поведение snprintf() совпадает с C99.
В glibc 2.1 добавлены модификаторы длины hh, j, t и z и символы преобразования a и A.
В glibc 2.2 добавлен символ преобразования F с семантикой C99, а также флаг I.
ЗАМЕЧАНИЯ¶
В некоторых программах неосмотрительно используется код
sprintf(buf, "%s some further text", buf);
для добавления текста в buf. Однако в стандартах явно сказано, что результат не определён, если буферы источника и приёмника перекрываются при вызовах sprintf(), snprintf(), vsprintf() и vsnprintf(). В зависимости о версии gcc(1) и указанных параметрах компилятора, подобные вызовы не приводят к ожидаемым результатам.
Реализация функций snprintf() и vsnprintf() в glibc 2.1 соответствует стандарту C99 как было описано выше. До glibc 2.0.6, они возвращали -1 при обрезанном выводе.
ДЕФЕКТЫ¶
Так как sprintf() и vsprintf() работают со строкой произвольной длины, вызывающие должны стараться не переполнить реальное пространство; часто это невозможно гарантировать. Заметим, что длина получаемых строк зависит от локали и её сложно предсказать. Вместо них используйте snprintf() и vsnprintf() (или asprintf(3) и vasprintf(3)).
Код, подобный printf(foo); часто означает ошибку, так как foo может содержать символ %. Если содержимое foo пришло из недоверительного пользовательского ввода, то в нём может содержаться %n, из-за чего вызов printf() сделать запись в память и создаст дыру в безопасности.
ПРИМЕРЫ¶
Печать Pi с пятью знаками:
#include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
Печать даты и времени в виде «Sunday, July 3, 10:02», где weekday и month указатели на строки:
#include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
weekday, month, day, hour, min);
Во многих странах используется порядок день-месяц-год. Вот печать аргументов в формате с учётом интернациональности:
#include <stdio.h> fprintf(stdout, format,
weekday, month, day, hour, min);
где format зависит от локали и может переставлять аргументы. Со значением:
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
получается «Sonntag, 3. Juli, 10:02».
Выделение достаточно большой строки и печать в неё (код работает и с glibc 2.0, и с glibc 2.1):
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) {
int n = 0;
size_t size = 0;
char *p = NULL;
va_list ap;
/* определим требуемый размер */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n < 0)
return NULL;
/* One extra byte for '\0' */
size = (size_t) n + 1;
p = malloc(size);
if (p == NULL)
return NULL;
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n < 0) {
free(p);
return NULL;
}
return p; }
Если происходит обрезание в версиях glibc до 2.0.6, то это считается ошибкой.
СМ. ТАКЖЕ¶
printf(1), asprintf(3), puts(3), scanf(3), setlocale(3), strfromd(3), wcrtomb(3), wprintf(3), locale(5)
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан Alexey, Azamat Hackimov <azamat.hackimov@gmail.com>, kogamatranslator49 <r.podarov@yandex.ru>, Kogan, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
1 ноября 2020 г. | GNU |