编译环境:
Debian: 7.6
gcc: 4.7.2
一、格式化输出函数 C语言中设计到的标准格式化输出函数如下:
#include
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include
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);
二、相互之间的关系 1、共同点: 在格式化字串的控制下,把数据输出到输出设备。格式化字串指定如何把后续的参数进行转化。如:
printf("%02x", 100); /* 输出是16进制 */
printf("%dx", 100); /* 输出是10进制 */
2、不同点: 按输出到的设备分:
| printf() vprintf() |
输出至标准输出流stdout |
| fprintf() vfprintf() |
输出至指定输出流 |
| sprintf() snprintf() vsprintf() vsnprintf() |
输出至字串str |
按是否指定操作字节分:
| snprintf() vsnprintf() |
写入至多size个字节(含'\0')到dtr |
| vprintf() vfprintf() vsprintf() vsnprintf() |
分别等同于:printf() fprintf() sprintf() snprintf() 区别是:它们都有va_list列表,一旦调用完毕,ap即成为“未定义”状态 |
3、返回值: 正常情况下,函数返回输出成功的字符个数(不含'\0')。若出错,返回负值。 snprintf()和vsnprintf()输出字符个数不超过size字节(含'\0'), 如果size小于字符串的长度(不含'\0'),字符串会被截断,返回值是字符串的长度(不含'\0'),如下: int len; char str_buf[100]; len = snprintf(buf, 10, "%s$", "1234567890123"); // len: 13, buf: "1234567890"
如果size大于数据缓冲区长度,缓冲区长度个字串会被复制,返回值是字符串的长度(不含'\0'),如下: char str_buf[5]; // len: 13, buf: "12345"
三、使用注意 1、在使用sprintf()和vsprintf()的时候,应确保数据大小不超出str缓冲区的大小,否则产生溢出,造成灾难。如果无法保证,应该选用snprintf()和vsnprintf()。
2、把字串加到原字串的后面,如下: sprintf(buf, "%s append text", buf); 在我用的gcc中,这种使用如期运行;但是,在有的gcc版本中,结果并不正确。所以,不要这样做。 而且,标准中明确指出,调用sprintf(), snprintf(), vsprintf(),vsnprintf()函数,如果源、目标地址重叠,结果是未定义的(undefined). 3、像这样的代码printf(foo);往往会引入bug。因为如果foo中包含“%n”将引起printf()对内存的写入并造成安全
漏洞。例如: printf("%n"); // Segmentation fault