printf_s
printf, fprintf, sprintf, snprintf, printf_s, fprintf_s
Defined in header | ||
---|---|---|
(1) | ||
int printf( const char *format, ... | (until C99) | |
int printf( const char *restrict format, ... | (since C99) | |
(2) | ||
int fprintf( FILE *stream, const char *format, ... | (until C99) | |
int fprintf( FILE *restrict stream, const char *restrict format, ... | (since C99) | |
(3) | ||
int sprintf( char *buffer, const char *format, ... | (until C99) | |
int sprintf( char *restrict buffer, const char *restrict format, ... | (since C99) | |
int snprintf( char *restrict buffer, int bufsz, const char *restrict format, ... | (4) | (since C99) |
int printf_s(const char *restrict format, ... | (5) | (since C11) |
int fprintf_s(FILE *restrict stream, const char *restrict format, ... | (6) | (since C11) |
int sprintf_s(char *restrict buffer, rsize_t bufsz, const char *restrict format, ... | (7) | (since C11) |
int snprintf_s(char *restrict buffer, rsize_t bufsz, const char *restrict format, ... | (8) | (since C11) |
从给定的位置加载数据,将它们转换为字符串等价物并将结果写入各种接收器。
1)将结果写入输出流stdout
。
2)将结果写入输出流stream
。
3)将结果写入字符串buffer
。如果要写入的字符串(加上终止的空字符)超过了指向的数组的大小,则行为未定义buffer
。
4)将结果写入字符串buffer
。最多bufsz
- 写入1个字符。结果字符串将以空字符结尾,除非bufsz
为零。如果bufsz
为零,则不会写入任何内容,并且buffer
可能是空指针,但返回值(将写入的字节数)仍然会计算并返回。
5-8)与(1-4)相同,只是在运行时检测到以下错误并调用当前安装的约束处理函数:
- 转换说明符
%n
存在于format
由于所有的边界检查功能,printf_s,fprintf_s,sprintf_s,和snrintf_s仅保证可供如果__STDC_LIB_EXT1__由实现所定义,并且如果用户定义__STDC_WANT_LIB_EXT1__的整数常数1,包括之前<stdio.h>。
参数
流 | - | 输出文件流写入 |
---|---|---|
缓冲 | - | 指向要写入的字符串的指针 |
bufsz | - | 最多bufsz - 可能会写入1个字符,再加上空终止符 |
格式 | - | 指向以空字符结尾的多字节字符串的指针,指定如何解释数据。 |
格式字符串由普通的多字节字符(除外%)组成,它们被不变地复制到输出流和转换规范中。每个转换规范具有以下格式: | ||
介绍%人物 | ||
(可选)一个或多个修改转换行为的标志: | ||
-:转换的结果在字段内左对齐(默认情况下它是右对齐的) | ||
+:带符号转换的符号总是预设为转换结果的前缀(默认情况下结果前面为减号,仅当它为负值时) | ||
空格:如果签名转换的结果不是以符号字符开头,或者是空的,则空格会预设为结果。如果+标志存在,它将被忽略。 | ||
#:执行转换的替代形式。请参阅下表以了解确切的效果,否则行为未定义。 | ||
0:对于整数和浮点数转换,前导零用于填充字段而不是空格字符。对于整数,如果明确指定了精度,它将被忽略。对于使用此标志的其他转换会导致未定义的行为。如果-标志存在,它将被忽略。 | ||
(可选)整数值或*指定最小字段宽度。如果需要,结果会填充空格字符(默认情况下),右侧对齐时填充空白字符,左侧填充右侧填充。在使用的情况下*,宽度由类型的附加参数指定int。如果参数的值是负数,则结果是-指定的标志和正的字段宽度。(注意:这是最小宽度:该值从不被截断。) | ||
(可选) .后面跟随整数或者*或者既不指定转换的精度。在使用的情况下*,精度由类型的附加参数指定int。如果这个参数的值是负数,它将被忽略。如果既不使用数字也不*使用,则精度取为零。请参阅下表以了解精确度的确切影响。 | ||
(可选) 长度修饰符,用于指定参数的大小 | ||
转换格式说明符 | ||
以下格式说明符可用: | ||
转换 | ||
说明符 | ||
长度修饰符 | ||
% | ||
c | ||
s | ||
d | ||
i | ||
o | ||
x | ||
X | ||
u | ||
f | ||
F | ||
e | ||
E | ||
a | ||
A | ||
(C99)。 | ||
g | ||
G | ||
n | ||
p | ||
浮点转换函数将无穷大转换为inf或infinity。使用哪一个是实现定义的。 | ||
非数字转换为nan或。使用哪一个是实现定义的。nan(char_sequence) | ||
该转换F,E,G,A输出INF,INFINITY,NAN来代替。 | ||
即使%c需要int参数,通过char调用可变参数函数时发生的整数提升也是安全的。 | ||
对于固定宽度的字符类型(正确的转换规格int8_t,等等)都在头中定义<inttypes.h>还(虽然PRIdMAX,PRIuMAX等是同义词%jd,%ju等)。 | ||
内存写入转换说明符%n是安全漏洞的常见目标,其中格式字符串取决于用户输入,并且不受边界检查printf_s函数族的支持。 | ||
每个转换说明符的操作之后都有一个序列点 ; 这允许将多个%n结果存储在相同的变量中,或者作为边缘情况,%n在相同的调用中打印由较早修改的字符串。 | ||
如果转换规范无效,则行为未定义。 | ||
... | - | 指定要打印的数据的参数 |
- 介绍
%
人物
以下格式说明符可用:
Conversion
说明符说明参数类型长度修饰符 hh
(C99)。
h
(none) l
ll
(C99).
j
(C99).
z
(C99).
t
(C99).
L
%
写文字%
。完整的转换规范必须是%%
。N / AN / AN / AN / AN / AN / AN / AN / AN / A c
写入单个字符
。该论点首先转换为unsigned char
。如果使用了l
修饰符,则首先将参数转换为字符串,就像通过具有参数的%ls一样
wchar_t[2]
。
N/A N/A int
wint_t
N / AN / AN / AN / AN / A s
写入字符串
参数必须是指向字符数组的初始元素的指针。Precision
指定要写入的最大字节数。如果未指定Precision
,则将每个字节写入并不包括第一个空终止符。如果使用了l
说明符,则参数必须是指向数组初始元素的指针wchar_t
,它将转换为char数组,就像通过调用wcrtomb
具有零初始化转换状态一样。
N/A N/A char*
wchar_t*
N/A N/A N/A N/A N/A d
i
将有符号的整数
转换为十进制表示形式-dddd
。 精度
指定出现的最小位数。默认的精度
是1
。
如果转换后的值和精度都是0
没有字符的转换结果。
signed char
short
int
long
long long
intmax_t
signed size_t
ptrdiff_t
N / A o
将无符号整数
转换为八进制表示oooo
。 精度
指定出现的最小位数。默认的精度
是1
。如果转换后的值和精度
都是0
没有字符的转换结果。在替代实现中,
如果需要,可以增加精度
以写入一个前导零。在这种情况下,如果转换值和精度
都是0
,0
写入单个。
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
uintmax_t
size_t
未签名的版本 ptrdiff_t
N/A x
X
将无符号整数
转换为十六进制表示hhhh
。使用x
转换字母abcdef
。
使用X
转换字母ABCDEF
。
精度
指定出现的最小位数。默认的精度
是1
。如果转换后的值和精度
都是0
没有字符的转换结果。在替代实现中,
0x
或者0X
如果转换后的值不为零,则将其作为结果的前缀。
N / A u
将无符号整数
转换为十进制表示形式dddd
。 精度
指定出现的最小位数。默认的精度
是1
。如果转换后的值和精度
都是0
没有字符的转换结果。
N/A f
F
将浮点数
转换为样式-ddd.ddd中
的小数表示法。 精度
指定小数点后面出现的最小位数。默认的精度
是6
。在替代实现
中,即使没有数字跟随,小数点字符也会被写入。对于无穷大和非数字转换风格,请参阅注释。
N/A N/A double
`double` (C99)
N/A N/A N/A N/A long double
`e`
E
将浮点数
转换为十进制指数符号。对于e
转换样式,使用-d.ddd
e
±dd
。
对于E
转换样式,使用-d.ddd
E
±dd
。
指数至少包含两位数字,只有在必要时才使用更多数字。如果值是0
,指数也是0
。精度
指定小数点后面出现的最小位数。默认的精度
是6
。在替代实现
中,即使没有数字跟随,小数点字符也会被写入。对于无穷大和非数字转换风格,请参阅注释。
N/A N/A N/A N/A N/A N/A a
A
(C99).
将浮点数
转换为十六进制指数表示法。对于a
转换样式- 使用
0x
h.hhh
p
±d
。
对于A
转换样式- 使用
0X
h.hhh
P
±d
。
0
如果参数不是标准化的浮点值,则第一个十六进制数字是。如果值是0
,指数也是0
。精度
指定小数点后面出现的最小位数。默认精度
足以精确表示值。在替代实现
中,即使没有数字跟随,小数点字符也会被写入。对于无穷大和非数字转换风格,请参阅注释。
N/A N/A N/A N/A N/A N/A g
G
根据值和精度
将浮点数
转换为十进制或十进制指数符号。对于风格转换的转换与风格或将被执行。gef
对于G
风格转换的转换与风格E
或F
将被执行。
让P
等于精度如果非零,6
如果没有指定精度,或者1
如果精度是0
。然后,如果具有样式的转换E
将具有以下指数X
:
- 如果P> X≥-4,转换是用式f或F和精度P - 1 - X。
除非请求替代表示,
否则尾随零将被删除,如果没有剩余小数部分,小数点字符也会被删除。对于无穷大和非数字转换风格,请参阅注释。
不适用/不适用/不适用/不适用/ n
返回此函数迄今为止写入的字符数
。结果写入
参数指向的值。规范可能不包含任何标志
,字段宽度
或精度
。
signed char*
short*
int*
long*
long long*
intmax_t
*
signed size_t
*
ptrdiff_t
*
N / A p
写入一个实现定义的字符序列来定义一个指针
。不适用不适用不适用不适用不适用不适用 void*
浮点转换函数将无穷大转换为inf
或infinity
。使用哪一个是实现定义的。
非数字转换为nan
或。使用哪一个是实现定义的。nan(char_sequence)
该转换F
,E
,G
,A
输出INF
,INFINITY
,NAN
来代替。
即使%c
需要int
参数,通过char
调用可变参数函数时发生的整数提升也是安全的。
对于固定宽度的字符类型(正确的转换规格int8_t<inttypes.h>还(虽然,等等)都在头定义PRIdMAX,PRIuMAX等是同义词%jd,%ju等)。
内存写入转换说明符%n
是安全漏洞的常见目标,其中格式字符串取决于用户输入,并且不受边界检查printf_s
函数族的支持。
每个转换说明符的操作之后都有一个序列点; 这允许将多个%n
结果存储在相同的变量中,或者作为边缘情况,%n
在同一个调用中打印由较早修改的字符串。
如果转换规范无效,则行为未定义。
... - arguments specifying data to print
返回值
1,2)发送到输出流的字符数或负值(如果发生输出错误或编码错误(用于字符串和字符转换说明符))
3)写入的字符数buffer
(不包括终止空字符);如果发生编码错误(用于字符串和字符转换说明符),则返回负值
4)buffer
如果bufsz
被忽略,将被写入的字符数(不包括终止空字符),或者如果编码错误(对于字符串和字符转换说明符)发生,则为负值
5,6)传输到输出流的字符数或负值(如果发生输出错误,运行时间约束违规错误或编码错误)。
7)写入的字符数buffer
,不包括空字符(只要buffer
不是空指针,bufsz
并且不为零且不大于RSIZE_MAX
),则不计入空字符,或者在运行时约束违规时为零,编码错误为负值
8)不包括终止空字符的字符数(只要buffer
不是空指针并且bufsz
不为零且不大于RSIZE_MAX
),buffer
如果bufsz
被忽略,将被写入的字符数或者如果运行时约束违规或编码错误发生
注意
C标准和POSIX指定sprintf
当参数与目标缓冲区重叠时,其行为及其变体未定义。例:
sprintf(dst, "%s and %s", dst, t // <- broken: undefined behavior
POSIX指定该errno
设置上的错误。它还指定了额外的转换规范,最显着的是支持参数重新排序(n$
紧接在%
指示n
'th参数之后)。
snprintf
使用零bufsz
和空指针调用buffer
对于确定包含输出所需的缓冲区大小很有用:
const char *fmt = "sqrt(2) = %f";
int sz = snprintf(NULL, 0, fmt, sqrt(2)
char buf[sz + 1]; // note +1 for terminating null byte
snprintf(buf, sizeof buf, fmt, sqrt(2)
snprintf_s
, just like snprintf
, but unlike sprintf_s
, will truncate the output to fit in bufsz-1
.
例
#include <stdio.h>
int main(void)
{
printf("Strings:\n"
const char* s = "Hello";
printf("\t.%10s.\n\t.%-10s.\n\t.%*s.\n", s, s, 10, s
printf("Characters:\t%c %%\n", 65
printf("Integers\n"
printf("Decimal:\t%i %d %.6i %i %.0i %+i %u\n", 1, 2, 3, 0, 0, 4, -1
printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6
printf("Octal:\t%o %#o %#o\n", 10, 10, 4
printf("Floating point\n"
printf("Rounding:\t%f %.0f %.32f\n", 1.5, 1.5, 1.3
printf("Padding:\t%05.2f %.2f %5.2f\n", 1.5, 1.5, 1.5
printf("Scientific:\t%E %e\n", 1.5, 1.5
printf("Hexadecimal:\t%a %A\n", 1.5, 1.5
}
输出:
Strings:
. Hello.
.Hello .
. Hello.
Characters: A %
Integers
Decimal: 1 2 000003 0 +4 4294967295
Hexadecimal: 5 a A 0x6
Octal: 12 012 04
Floating point
Rounding: 1.500000 2 1.30000000000000004440892098500626
Padding: 01.50 1.50 1.50
Scientific: 1.500000E+00 1.500000e+00
Hexadecimal: 0x1.8p+0 0X1.8P+0
参考
- C11标准(ISO / IEC 9899:2011):