pub unsafe fn printf(w: impl Write, format: CStr<'_>, ap: VaList<'_>) -> c_intExpand description
Implementation of printf formatting function, generic over a writer
This implementation in currently compliant over C17 specification (lacking a few one from C23) and contains extensions as well.
§The Format Specification
%[conversion-flags][field-width][precision][length-modifier]<conversion-format>§Conversion Flags
Conversion flags are flags that modify the behavior of the conversion format. Each one can happen only once per format specifier. They are:
-: The result of the conversion is left-justified within the field (by default it is right-justified).+: The sign of signed conversions is always prepended to the result of the conversion (by default the result is preceded by minus only when it is negative).(space): If the result of a signed conversion does not start with a sign character, or is empty, space is prepended to the result.- It is ignored if
+flag is present.
- It is ignored if
#: Alternative form of the conversion is performed. See the documentation for each conversion format for details.0: For integer and floating-point number conversions, leading zeros are used to pad the field instead of space characters.- For integer numbers it is ignored if the precision is explicitly specified.
- For other conversions using this flag results in undefined behavior.
- It is ignored if
-flag is present.
§Field Width
Specifies minimum field width. This makes the result to be padded (with spaces by default, with
zeroes if 0 conversion flag is specified) if the converted value has fewer characters than the
specified width. It can take three forms:
Nwhere N is a positive integer: Specifies the field width value ofN.*: The width is specified by an extra argument of typeint, which has to appear before the argument to be converted and the precision (if specified with.*).- If the value of e extra argument is negative, it is interpreted as with
-[conversion flag], i.e. left-justified result.
- If the value of e extra argument is negative, it is interpreted as with
*P$where P is a positive integer: The width is specified by an extra argument of typeint, which has to appear exactly at the position specified byP.- This is a popular extension of the C and POSIX standards.
- If the value of e extra argument is negative, it is interpreted as with
-[conversion flag], i.e. left-justified result.
§Precision
Specifies the precision of the conversion.
For integer [conversion formats], this specifies the number of digits to appear in the result.
For float point [conversion formats], this specifies the number of digits to appear after the decimal-point character.
It can take three forms:
.Nwhere N is a positive integer: Specifies the precision value ofN..*: The precision is specified by an extra argument of typeint, which has to appear before the argument to be converted and after the the field width (if specified with*).- If the value of the extra argument is negative, it is interpreted as if the precision were omitted.
.*P$where P is a positive integer: The precision is specified by an extra argument of typeint, which has to appear exactly at the position specified byP.- This is an popular extension of the C and POSIX standards.
- If the value of e extra argument is negative, it is interpreted as if the precision were omitted.
§Length Modifier
Specifies the size of the argument. In combination with the conversion format, it specifies the type of the corresponding argument.
hh: Byte size- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
h: Short size- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
l: Long size- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with character conversion format (
c) - Works with string conversion format (
s) - Works with written number conversion format (
n) - Works with float conversion formats (
f,F,e,E,a,A,g,G) (C99)
- Works with integer conversion formats (
ll: Long long size- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
j: Maximum width- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
z: Pointer width size- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
t: Pointer diff width- Works with integer conversion formats (
d,i,o,x,X,b,B) - Works with written number conversion format (
n)
- Works with integer conversion formats (
wN(C23 ※): Specifies that the size should be N bits width version of the supported conversion format.- Works with integer conversion formats (
d,i,o,x,X,b,B) - The supported values of
Nmust be the same as the widths specified instdint.h
- Works with integer conversion formats (
wfN(C23 ※): Specifies that the size should be the fast N bits width version of the supported conversion format.- Works with integer conversion formats (
d,i,o,x,X,b,B) - The supported values of
Nmust be the same as the widths specified instdint.h
- Works with integer conversion formats (
L: Long double size- Works with float conversion formats (
f,F,e,E,a,A,g,G)
- Works with float conversion formats (
H(C23 ※): _Decimal32 size- Works with float conversion formats (
f,F,e,E,a,A,g,G)
- Works with float conversion formats (
D(C23 ※): _Decimal64 size- Works with float conversion formats (
f,F,e,E,a,A,g,G)
- Works with float conversion formats (
DD(C23 ※): _Decimal128 size- Works with float conversion formats (
f,F,e,E,a,A,g,G)
- Works with float conversion formats (
§Conversion Format
Specifies the conversion format as one of the following:
%: Writes a percent symbol. The full conversion format must be%%.c: Writes as single character- Without length modifier:
- The argument is first converted to
unsigned char
- The argument is first converted to
- With
llength modifier:- The argument is first converted to a character string as if by
%lswith a array of 2wchar_targument.
- The argument is first converted to a character string as if by
- Without length modifier:
s: Writes a character string- The argument is a pointer to the first character
- The precision specifies the maximum number of bytes to be written. If not specified, writes up to the first null character found.
dandi: Writes a decimal representation of a signed integer- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The precision specifies the minimal number to appear (defaults to
u: Writes the decimal representation of a unsigned integer- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The precision specifies the minimal number to appear (defaults to
o: Writes the octal representation of a unsigned integer.- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The alternative representation includes a leading
0. - The types are the same as
u
- The precision specifies the minimal number to appear (defaults to
x: Writes the hexadecimal representation of a unsigned integer with lowercase characters.- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The alternative representation includes a leading
0x. - The types are the same as
u
- The precision specifies the minimal number to appear (defaults to
X: Writes the hexadecimal representation of a unsigned integer with uppercase characters.- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The alternative representation includes a leading
0X. - The types are the same as
u.
- The precision specifies the minimal number to appear (defaults to
b|B(C23): Writes the binary representation of a unsigned integer.- The precision specifies the minimal number to appear (defaults to
1). - If the precision is zero and the value to be written is also zero, the result is no characters written.
- The alternative representation includes a leading
0band0B, respectively. - The types are the same as
u.
- The precision specifies the minimal number to appear (defaults to
f|F: Writes the decimal representation of a float point number.- The precision specifies the exact number of digits to appear after the decimal point
character (defaults to
6). - The alternative representation, the decimal point character is written even if no digits follow it.
- The precision specifies the exact number of digits to appear after the decimal point
character (defaults to
e|E: Writes the float point number with the decimal exponential notation ([-]d.ddd e±dd | [-]d.ddd E±dd)- The precision specifies the exact number of digits to appear after the decimal point
character (defaults to
6). - The exponent contains at least two digits, more digits are used only if necessary.
- If the value is zero, the exponent is also zero.
- The alternative representation: decimal point character is written even if no digits follow it.
- The precision specifies the exact number of digits to appear after the decimal point
character (defaults to
a|A: Writes the float point number with the hexadecimal exponential notation ([-] 0xh.hhh p±d | [-] 0Xh.hhh P±d)- The precision specifies the exact number of digits to appear after the hexadecimal point
character (defaults to
6). - If the value is zero, the exponent is also zero.
- The alternative representation: decimal point character is written even if no digits follow it.
- The precision specifies the exact number of digits to appear after the hexadecimal point
character (defaults to
g|G: Writes the float point number to decimal or decimal exponent notation depending on the value and the precision.- Let
Pequal the precision if nonzero,6if the precision is not specified, or1if the precision is0. Then, if a conversion with styleEwould have an exponent ofX:- If
P > X ≥ −4, the conversion is with the formatfand precisionP − 1 − X. - Otherwise, the conversion is with the format
eorEand precisionP − 1.
- If
- Unless alternative representation is requested, the trailing zeros are removed. Also the decimal point character is removed if no fractional part is left.
- Let
n: Writes the number of characters written in the call into the argument pointer- It can not contain any [conversion flag], field width, or precision.
p: Writes an implementation defined character sequence defining a pointer.
§Types
The types expected by the format string can change with the length modifier.
For the c:
For the s:
- Without length modifier: pointer to
char(char*,const char*) - With
llength modifier: pointer towchar_t(wchar_t*,const wchar_t*)
For the d and i:
- Without length modifier:
int - With
hhlength modifier:signed char - With
hlength modifier:short - With
llength modifier:long - With
lllength modifier:long long - With
jlength modifier:intmax_t - With
zlength modifier:ssize_t - With
tlength modifier:ptrdiff_t
For the u, o, x, X, b, B:
- Without length modifier:
unsigned int - With
hhlength modifier:unsigned char - With
hlength modifier:unsigned short - With
llength modifier:unsigned long - With
lllength modifier:unsigned long long - With
jlength modifier:uintmax_t - With
zlength modifier:size_t - With
tlength modifier:unsigned ptrdiff_t
For the f, F, e, E, a, A, g, G:
- Without length modifier:
double - With
llength modifier:double - With
Llength modifier:long double - With
Hlength modifier (C23 ※):_Decimal32 - With
Dlength modifier (C23 ※):_Decimal64 - With
DDlength modifier (C23 ※):_Decimal128
For the n
- Without length modifier: pointer to
int(int*) - With
hhlength modifier: pointer tosigned char(signed char*) - With
hlength modifier: pointer toshort(short*) - With
llength modifier: pointer tolong(long*) - With
lllength modifier: pointer tolong long(long long*) - With
jlength modifier: pointer tointmax_t(intmax_t*) - With
zlength modifier: pointer tossize_t(ssize_t*) - With
tlength modifier: pointer toptrdiff_t(ptrdiff_t*)
For the p, it must always be a pointer to void (void* | const void*)
§Safety
Behavior is undefined if any of the following conditions are violated:
apmust follow the safety contract of variable arguments of C.