C语言格式化输出函数及使用禁区



受不了xxxx恶心人的行为,遂搬迁至博客园。 始发:2014-09-18 20:01:17
 

一、格式化输出函数

C语言中设计到的标准格式化输出函数如下:
 1 #include <stdio.h>
 2 int printf(const char *format, ...);
 3 int fprintf(FILE *stream, const char *format, ...);
 4 int sprintf(char *str, const char *format, ...);
 5 int snprintf(char *str, size_t size, const char *format, ...);
 6  
 7 #include <stdarg.h>
 8 int vprintf(const char *format, va_list ap);
 9 int vfprintf(FILE *stream, const char *format, va_list ap);
10 int vsprintf(char *str, const char *format, va_list ap);
11 int vsnprintf(char *str, size_t size, const char *format, va_list ap);
 

二、相互之间的关系

1、共同点

在格式化字串的控制下,把数据输出到输出设备。格式化字串指定如何把后续的参数进行转化。如:
1 printf("%x", 100);    /* 输出是16进制 */
2 printf("%d", 100);     /* 输出是10进制 */

2、不同点

按输出到的设备分:
printf()
vprintf()
输出至标准输出流stdout
fprintf()
vfprintf()
输出至指定输出流
sprintf()
snprintf()
vsprintf()
vsnprintf()
输出至字串str
 
 
 
 
 
 
 
 
 
 
按是否指定操作字节分:
snprintf()
vsnprintf()
写入至多size个字节(含'')到dtr
vprintf()
vfprintf()
vsprintf()
vsnprintf()
分别等同于:printf()
fprintf()
sprintf()
snprintf()
区别是:它们都有va_list列表,一旦调用完毕,ap即成为“未定义”状态
 
 
 
 
 
 
 
 

3、返回值

正常情况下,函数返回输出成功的字符个数(不含'')。若出错,返回负值。
snprintf() 和 vsnprintf() 输出字符个数不超过 size 字节(含''),
如果size小于字符串的长度(不含''),字符串会被截断,返回值是字符串的长度(不含''),如下:

1 int  len;
2 char str_buf[100];
3 len = snprintf(str_buf, 10, "%s", "1234567890123");
4 // len: 13, buf: "123456789"

如果size大于数据缓冲区长度,那代码肯定是有问题的!!!

*** stack smashing detected ***: ./test terminated
Aborted (core dumped)

三、使用注意

1、在使用sprintf()和vsprintf()的时候,应确保数据大小不超出str缓冲区的大小,否则产生溢出,造成灾难。如果无法保证,应该选用snprintf()和vsnprintf()。

2、把字串加到原字串的后面,如下:
sprintf(buf, "%s append text", buf);
在我用的gcc中,这种使用如期运行;但是,在有的gcc版本中,结果并不正确。所以,不要这样做。
而且,标准中明确指出,调用sprintf(), snprintf(), vsprintf(),vsnprintf()函数,如果源、目标地址重叠,结果是未定义的(undefined)。

C99 and POSIX.1-2001 specify that the results are undefined if  a  call
to  sprintf(), snprintf(), vsprintf(), or vsnprintf() would cause copy‐
ing to take place between objects that overlap  (e.g.,  if  the  target
string  array and one of the supplied input arguments refer to the same
buffer)

3、像这样的代码printf(foo);往往会引入bug。因为如果foo中包含“%n”将引起printf()对内存的写入并造成安全漏洞。例如:

printf("%n");    // Segmentation fault
原文地址:https://www.cnblogs.com/rockyching2009/p/13129390.html