PRINTF(3)

НАЗВАНИЕ
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - выводят данные с преобразованием формата

СИНТАКСИС
#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, 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 vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);

ОПИСАНИЕ
Функции семейства printf выводят данные в соответствии с параметром format, описанным ниже. Функции printf и vprintf направляют данные в стандартный поток вывода stdout; fprintf и vfprintf направляют данные в заданный поток вывода stream; sprintf, snprintf, vsprintf и vsnprintf направляют данные в символьную строку str.

Функции vprintf, vfprintf, vsprintf, vsnprintf эквивалентны соответствующим функциям printf, fprintf, sprintf, snprintf, исключая то, что они вызываются с va_list, а не с переменным количеством аргументов. Эти функции не вызывают макрос va_end , и поэтому значение ap после вызова неопределенно. Приложение может позже само вызвать va_end(ap).

Эти восемь функций выводят данные в соответствии со строкой format, которая определяет, каким образом последующие параметры (или доступные параметры переменной длины из stdarg(3)) преобразуют поток вывода.

  Возвращаемое значение
При успешном завершении работы эти функции возвращают количество напечатанных символов (не включая завершающий `\0', использующийся для обозначения конца строки данных). Функции snprintf и vsnprintf передают не больше байтов, чем указано в переменной size (включая завершающий '\0'). Если вывод был урезан из-за этого ограничения, то возвращаемое значение является числом символов (кроме заверщающего '\0'), переданных в конечной строке, если для этого имелось достаточно места. Таким образом, возвращаемое значение size или более обозначает, что вывод был обрезан. (См. также ниже "ПРИМЧАНИЯ"). Если случилась ошибка вывода, то возвратится отрицательное значение.

  Структура строки параметров
Cтрока параметров - это строка символов из переменных параметров. Эта строка может состоять из нуля или более параметров: обычных символов (кроме %), которые неизменно копируются в поток выхода; и спецификаторов преобразования, за каждым из которых следует один или более параметров. Каждый спецификатор преобразований предваряется символом % и оканчивается спецификатором преобразования. Между ними могут находиться (в определенном порядке) ноль или более флагов, необязательная минимальная ширина поля, необязательная точность и необязательные модификаторы длины. Параметры должны точно соответствовать (после преобразования типа) спецификаторам преобразований. По умолчанию параметры используются в порядке поступления, где каждая `*' и каждый спецификатор преобразования требуют последующего параметра (если указано недостаточно параметров, то это приведет к ошибке). Возможно явное указание на то, какой параметр будет следующим, с помощью записи `%m$' вместо `%' и `*m$' вместо `*', где десятичная цифра m означает позицию нужного параметра в их списке*; список начинается с единицы. Таким образом,
    	printf("%*d", width, num);
и
    	printf("%2$*1$d", width, num);
означают одно и то же. Вторая форма записи позволяет производить указание на тот же параметр несколько раз. Стандарт C99 не поддерживает использование `$', который пришел из Single Unix Specification. Если используется `$', то он должен использоваться для всех преобразований аргументов и во всех аргументах ширины и точности, но он может быть смешан с форматами `%%', которые не поглощают аргументы. Там может не быть пробелов между числами аргументов, обусловленные использованием `$'. Например, если аргументы 1 и 3 определены, аргумент 2 должен также быть определен где-то в строке формата. В некоторых цифровых преобразованиях используется символ десятичной точки или символ тысячной группировки `,'. Текущий символ зависит от переменной LC_NUMERIC. Стандарт 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 игнорируется. Поведение флага при других преобразованиях не определено.

-   Выравнивает результат преобразования по левой границе поля. (По умолчанию выравнивание выполняется справа.) Исключает преобразование типа n , дополняя значение справа пробелами. - Отменяет флаг 0, если оба флага были установлены.

' ' (пробел). Устанавливает перед положительными числами (или пустой строкой) знак пробела для знаковых преобразований.

+   Знак + или - всегда помещается перед числом со знаком. По умолчанию знак используется только для отрицательных чисел. + отменяет действие пробела, если оба флага используются.

Пять флагов, описанных выше, определены в стандарте C. В стандарте SUSv2 определен один дополнительный флаг.

'   При десятичных преобразованиях (i, d, u, f, g, G) данные группируются символом тысячной группировки, если информация локализации не указывает на это. Обратите внимание, что многие версии gcc не могут распознать эту опцию и выводят соответствующее предупреждение. SUSv2 не включает %'F.

glibc 2.2 добавит в будущем этот флаг.

I   При преобразовании целых десятичных чисел (i, d, u) вывод использует локальное представление цифр (например арабские цифры). Однако он не включает все локальные определения как определено в outdigits. См. http://sources.redhat.com/ml/libc-alpha/2000-08/msg00230.html

  Ширина поля
Необязательная стpока из десятичных цифp (с пеpвой цифpой, отличной от нуля) опpеделяет минимальную шиpину поля. Если пpеобpазованное значение имеет меньшее количество знаков, чем шиpина поля, то оно слева дополняется пpобелами (или спpава, если указан флаг левого пpеобpазования). Вместо стpоки десятичных цифp можно указать `*' или `*m$' (для некотоpого десятичного числа m), чтобы опpеделить шиpину поля по шиpине следующего аpгумента или аpгумента с номером m соответственно. Аргументы должны иметь тип int. Отpицательная шиpина поля пpинимается как флаг `-', устанавливающий положительную шиpину поля. Несуществующая или небольшая шиpина поля не делает его усеченным; если pезультат пpеобpазования больше шиpины поля, то поле pасшиpяется, чтобы вместить в себя пpеобpазованное значение.

  Точность
Необязательный паpаметp точности в виде знака точки (`.') сопpовождается необязательной стpокой десятичных цифp. Вместо стpоки десятичных цифp можно указать `*' или `*m$' (для некотоpого десятичного числа m), чтобы опpеделить значение точности по следующему аpгументу или аpгументу с номером m соответственно, котоpые должны иметь тип int. Если точность указана как `.' или отpицательна, то она обрабатывается как нулевая. Это позволяет ограничивать количество выводимых символом для преобразований типов: 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   Целые преобразователи соответствуют аргументам short int или unsigned short int; а также тип преобразования n соответствует аргументу указателя short int.

l   Целый преобразователь соответствует аргументам long int или unsigned long int; тип преобразования n соответствует аргументу указателя long int; тип преобразования c соответствует аргументу wint_t; тип преобразования s соответствует агрументу указателя wchar_t.

ll  Целые преобразователи соответствуют аргументу long long int или unsigned long long int; тип преобразования n соответствует аргументу указателя long long int .

L   Типы преобразования: a, A, e, E, f, F, g или G соответствуют аргументу longdouble. (C99 поддерживает %LF, а SUSv2 - нет.)

q   (Только для библиотеки libc5 в BSD 4.4 и Linux. Не используйте их.) Это синоним ll.

j   Целые преобразователи соответствуют аргументу intmax_t или uintmax_t.

z   Целые преобразователи соответствуют аргументу size_t или ssize_t. (Linux libc5 использует для этого Z. Не используйте данный аргумент.)

t   Целые преобразователи соответствуют аргументу ptrdiff_t.

SUSv2 располагает информацией только о модификаторах длины h (с hd, hi, ho, hx, hX, hn); l (с ld, li, lo, lx, lX, ln, lc, ls) и L (с Le, LE, Lf, Lg, LG).

  Тип преобразования
Символы, которые определены как типы преобразования. Типы преобразования и их значения:

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

o,u,x,X
    Параметр unsigned int преобразуется в беззнаковое восьмеричное выражение (o), беззнаковое десятичное (u) или беззнаковое шестнадцатеричное (x и X). Буквы abcdef используются для преобразования x, а буквы ABCDEF - для преобразования X. Точность задает минимальное количество цифр в изображении результата; если результат можно показать с помощью меньшего количества цифр, то слева добавляются незначащие нули. По умолчанию значение точности равно единице. При выводе нуля с нулевой точностью выходной поток пуст.

e,E Параметр double округляется и преобразуется в десятичное отображение в виде [-]d.ddde\*(Pmdd, где одна цифра перед символом десятичной точки и количество цифр после нее указывают на необходимую точность; если точность отсутствует, она считается равной 6-и; если точность равна нулю, символ десятичной точки не показывается. Преобразование E использует букву E (чаще e) для отображения экспоненты. Экспонента всегда содержит две последние цифры; если ее значение равно нулю, экспонента равна 00.

f,F Параметр double округляется и преобразуется в десятичное выражение в виде [-]ddd.ddd, где количество цифр после десятичной точки указывает на требуемую точность. Если точность отсутствует, она принимается равной 6-и; если точность равна нулю, десятичная точка не показывается. Если десятичная точка есть, перед ней должна быть минимум одна цифра. (SUSv2 не располагает информацией о типе F и указывает, что этот символ предназначен для отображения символов бесконечности и NaN. Стандарт 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; в SUSv2 этого нет). Для преобразования типа a параметр double отображается в шестнадцатеричной форме (с помощью букв abcdef) вида [-]0xh.hhhhp\*(Pmd; для преобразований типа A используется префикс 0X, буквы ABCDEF и экспонентный разделитель P. Точность равна шестнадцатеричному разряду перед десятичной точкой и количеству цифр после нее. По умолчанию точность принимается равной точному значению разряда, если оно соответствует ему по основанию 2, и в противном случае размер ее является достаточным для определения значения типа double. Разряд перед десятичной точкой не определен для ненормализованных чисел и не равен нулю, но не определен для нормализованных чисел.

c   Если модификатор l не представлен, параметр int преобразуется в unsigned char и выводится как результирующее значение. Если модификатор l представлен, параметр wint_t (расширенные символы) преобразуется в многобайтовую пследовательность для вызова в функции wcrtomb; первое его значение преобразуется в начальное значение и выводится в виде многобайтовой строки.

s   Если модификатор l не представлен: параметр const char * преобразуется в указатель на массив символьного типа (строковый указатель). Символы из массива выводятся до заканчивающего символа NUL (не включая его); если точность определена, выводится не более установленного количества символов. Если точность указана, нулевой символ не нужен; если точность не указана или она больше, чем размер массива, массив должен содержать заканчивающий символ NUL. Если модификатор l присутствует: параметр const wchar_t * преобразуется в указатель на массив с расширенными символами. Расширенные символы из массива преобразуются в многобайтовые символы (которые вызываются функцией wcrtomb; при этом первое значение преобразуется в начальное значение первого расширенного символа) и содержат завершающий нулевой символ. Результирующие многобайтовые символы выводятся до завершающего нулевого байта (не включая его). Если точность определена, выводится количество байтов, не превышающее это значение, а оставшаяся часть многобайтовых символов не выводится. Помните, что точность определяется числом выводимых байтов, а не расширенных символов или экранной позиции. Массив должен содеpжать конечный нулевой символ, если точность не указана, и содеpжать количество байтов, меньшее pазмеpа массива.

C   (Этого нет в C99, но есть в SUSv2.) Синоним lc. Не следует использовать.

S   (Этого нет в C99, но есть в SUSv2.) Синоним ls. Не следует использовать.

p   Параметр указателя void *, выводящийся в шестнадцатеричном виде (так же, как %#x или %#lx).

n   Количество символов, выводящихся в целом типе int * (или других) без преобразующих параметров.

%   Выводит символ `%' без преобразующих параметров. Полный спецификатор преобразования - `%%'.

ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ
Печатает с пятью десятичными знаками после десятичной точки:
    #include <math.h>
    #include <stdio.h>
    fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));

Печатает дату и вpемя в фоpме `Sunday, July 3, 10:02', где weekday и month являются указателями на стpоку:
    #include <stdio.h>
    fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
    	weekday, month, day, hour, min);

Многие стpаны используют поpядок отобpажения даты в виде "день, месяц, год". Следовательно, междунаpодная веpсия должна отображать значений в pазличных стандаpтах:
    #include <stdio.h>
    fprintf(stdout, format,
    	weekday, month, day, hour, min);
где format зависит от локальных установок и может менять аpгументы. Оперируя значениями
    "%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
, можно получить `Воскресенье, 3. Июль, 10:02'.

Указание достаточно большой строки и ее вывод (код корректен для обеих версий: glibc 2.0 и glibc 2.1):
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    char *
    make_message(const char *fmt, ...) {
       /* необходимо не более 100-а байтов. */
       int n, size = 100;
       char *p;
       va_list ap;
       if ((p = malloc (size)) == NULL)
          return NULL;
       while (1) {
          /* Попытайтесь произвести печать в pазpешенном пpостpанстве. */
          va_start(ap, fmt);
          n = vsnprintf (p, size, fmt, ap);
          va_end(ap);
          /* Если выполнено, возвpатить стpоку. */
          if (n > -1 && n < size)
             return p;
          /* Произвести повторную попытку, с пространством большего размера. */
          if (n > -1)    /* glibc 2.1 */
             size = n+1; /* Это то, что необходимо */
          else           /* glibc 2.0 */
             size *= 2;  /* Удвоить стаpый pазмеp */
          if ((p = realloc (p, size)) == NULL)
             return NULL;
       }
    }

СООТВЕТСТВИЕ СТАНДАРТАМ
Функции fprintf, printf, sprintf, vprintf, vfprintf, и vsprintf соответствуют ANSI X3.159-1989 (``ANSI C'') и ISO/IEC 9899:1999 (``ISO C99''). Функции snprintf и vsnprintf соответствуют ISO/IEC 9899:1999.

Что касается возвpащаемого значения snprintf, то стандаpты SUSv2 и C99 пpотивоpечат дpуг дpугу: когда snprintf вызывается с size=0, тогда SUSv2 пpедусматpивает неопpеделенную величину возвpата, меньшую единицы, а C99 устанавливает в этом случае str pавной NULL и возвpащает значение (как обычно) в виде числа символов, размер которых в выходной стpоке был бы достаточным.

Библиотека Linux libc4 располагает информацией о пяти стандартных флагах C. Она также знает о модификаторах длины g, l, L и преобразованиях cdeEfFgGinopsuxX, где F является синонимом f. Дополнительно она принимает D, O, U как синонимы ld, lo, lu. (Это плохо и привело позже к серьезной ошибке, когда исчезла поддержка %D.) Зависимые от локали символы системы исчисления, разделители тысяч, бесконечность, %m$ и *m$ не поддерживаются.

Библиотека Linux libc5 располагает информацией о пяти стандартных флагах C и флагах локализации, %m$ и *m$, о модификторах длины h,l,L,Z,q, но соотносит типы L и q с long double и сверхдлинным целым (это ошибка). Данная библиотека больше не распознает FDOU, но содержит новый символ преобразования m, который выводит strerror(errno).

glibc 2.0 сейчас поддерживает символы C и S.

К glibc 2.1 добавлены модификаторы длины hh,j,t,z и символы преобразования a,A. В glibs 2.2 добавлены символы преобразования F с семантикой C99 и флаг I.

ПРИМЕЧАНИЯ ПО ИСТОРИИ
В Unix V7 были определены три функции: printf, fprintf, sprintf - а также имелись: ширина или точность *, модификатор длины l, типы преобразования doxfegcsu, а также D,O,U,X (как синонимы ld,lo,lu,lx). Это до сих пор является справедливым для BSD 2.9.1, но в BSD 2.10 уже имеются флаги #, + и <space>, хотя нет упоминаний о D,O,U,X. В BSD 2.11 появились vprintf, vfprintf, vsprintf. Предупреждение: не используйте D,O,U,X. В BSD 4.3 Reno были: 0, модификаторы длины h и L, типы преобразований n, p, E, G, X (с их текущими значениями); в этой версии осуждалось использование D,O,U. В BSD 4.4 представлены функции snprintf, vsnprintf и модификатор длины q. FreeBSD также имела функции ff , asprintf и vasprintf, которые создавали буфер, достаточный для sprintf. В glibc имеются функции dprintf и vdprintf, которые вместо потока выводят в файловый дескриптор.

НАЙДЕННЫЕ ОШИБКИ
Так как sprintf и vsprintf получают строки произвольной длины, их вызов может привести к переполнению буфера, что невозможно предотвратить. Обратите внимание, что длина строки определена как локально зависимая и ее трудно спрогнозировать. Используйте вместо них snprintf и vsnprintf (или asprintf и vasprintf).

Библиотека Linux libc4.[45] не имеет функции snprintf, однако предоставляет libbsd, содержащую snprintf, эквивалентную sprintf, то есть игнорирующую аргумент size. Таким образом, использование snprintf с ранними версиями libc4 ведет к серьезным проблемам с безопасностью.

Код типа printf(foo); часто приводит к ошибке, если foo может содержать символ %. Если в foo записан непроверенный ввод пользователя, то содержит foo может содержать %n, и это вызовет запись в память и создание бреши в безопасности.

Некоторые преобразования чисел с плавающей запятой в ранних версиях libc4 приводили к утечкам памяти.

ЗАМЕЧАНИЯ
Реализация glibc функций snprintf и vsnprintf соответствует стандарту C99, т.е. функции ведут себя так, как описано выше, начиная с glibc версии 2.1. До glibc 2.0.6 они возвращают -1 при обрезании вывода.

СМ. ТАКЖЕ
printf(1), asprintf(3), dprintf(3), wcrtomb(3), wprintf(3), scanf(3), locale(5)