printf学习笔记
输出重定向流的概念程序输入或输出的一个连续的字节序列在C语言中,所有流均以文件的形式出现C语言中提供的5中标准流
利用shell的I/O进行输出重定向在Linux下,文本流和二进制流是相同的流与文件的连接重定向符标准错误重定向为什么要进行重定向
使用freopen重定向输入输出流
打印文件名,函数名,行号ANSIC标准中的几个标准预定义宏C99新增的预定义宏
使用printf插桩定位带来的问题解决行缓冲带来的延迟打印
打印开关控制日志是有代价的C99标准对可变参数宏的支持
打印等级控制内核打印等级
输出重定向
流的概念
程序输入或输出的一个连续的字节序列
设备(鼠标、键盘、打印机、屏幕…)的输入输出使用流来处理
在C语言中,所有流均以文件的形式出现
统一了各种硬件操作接口带来的差异
C语言中提供的5中标准流
利用shell的I/O进行输出重定向
在Linux下,文本流和二进制流是相同的
文本流是由文本行组成的序列,以’\n’结尾(或有回车符换行符代替),二进制流由未经处理的字节组成
流与文件的连接
打开一个流,该流将与一个文件连接起来,关闭流则断开连接指向该打开文件的指针记录了控制该流的信息程序执行时,默认会打开stdin、stdout和stderr三个文件
重定向符
输出重定向:>、>>、>! [重定向,追加,强制重定向]输入重定向:< [输入重定向]
标准错误重定向
2>:标准错误重定向到一个文件,并覆盖原来的文件(b-shell)2>>:标准错误重定向到一个文件(追加)。1>默认为 >2>&1:将标准错误重定向到标准输出>&:将一个输出重定向到另一个句柄的输入中
为什么要进行重定向
将屏幕输出的重要信息保存下来有时候不希望打印干扰屏幕正确和错误的信息需要分别输出时
使用freopen重定向输入输出流
输出重定向错误重定向
#include <stdio.h>
int main() {
printf("hello world\n");
if(NULL == freopen("./test.log","w",stdout)) {
fprintf(stderr,"redirecing stdout error!\n");
}
else {
printf("this is ./test.log\n");
fclose(stdout);
}
if(NULL == freopen("./err.log","w",stderr)) {
fprintf(stderr,"redirecing stdout error!\n");
}
else {
fprintf(stderr,"this is ./err.log\n");
fclose(stderr);
}
return 0;
}
打印文件名,函数名,行号
ANSIC标准中的几个标准预定义宏
LINE:在源代码中插入当前源代码行号FILE:在源文件中插入当前源文件名FUNCTION:函数名DATE:在源文件中插入当前的编译日期TIME:在源文件中插入当前编译时间STDC:当程序严格遵循ANSI C标准时该标识被赋值为1func:函数名,C99新增加的
C99新增的预定义宏
VA_ARGS:用于支持不定参数的宏定义
使用printf插桩定位带来的问题
以下程序运行并不会每秒打印一次,而是在main函数执行结束一次性打印.printf行缓冲机制
减少I/O时间与磁盘读写的时间
缓冲机制
#include <unistd.h>
#include <stdio.h>
int main() {
printf("delay 1"); sleep(1);
printf("delay 1"); sleep(1);
printf("delay 3"); sleep(1);
printf("delay 4"); sleep(1);
printf("delay 5"); sleep(1);
}
解决行缓冲带来的延迟打印
通过添加换行符可以解决或者当printf缓冲满后会打印在printf里添加\n刷新一下缓冲区:fflush(stdout);直接将缓冲区禁掉: setvbuf(stdout,NULL,_IONBF,0);使用错误标准流,stdout有line buffer:fprintf(stderr,…)
打印开关控制
日志是有代价的
尤其是在嵌入式对时序要求较高的场景打印会影响系统性能
C99标准对可变参数宏的支持
VA_ARGS
#include <stdio.h>
#define __DEBUG
#ifdef __DEBUG
#define DEBUG(msg,...) printf(msg,##__VA_ARGS__)
#else
#define DEBUG(msg,...)
#endif
int main() {
DEBUG("hello dubug\n");
DEBUG("%s %d \n","this is debug app \n",10000);
return 0;
}
#include <stdio.h>
#define __DEBUG
#ifdef __DEBUG
#define DEBUG(...) printf(__VA_ARGS__)
#else
#define DEBUG(...)
#endif
int main() {
DEBUG("hello dubug\n");
DEBUG("%s %d \n","this is debug app \n",10000);
return 0;
}
打印等级控制
#include <stdio.h>
#define ERR_LEVEL 3
#define WARN_LEVEL 2
#define DEBUG_LEVEL 1
#define PRINTF_LEVEL 4
#define ERR(...) \
do { \
if(PRINTF_LEVEL >= ERR_LEVEL) { \
printf(__VA_ARGS__); \
} \
}while(0)
int main() {
ERR("err \n");
return 0;
}
内核打印等级
#define KERN_EMERG KERN_SOH “0” /* system is unusable / #define KERN_ALERT KERN_SOH “1” / action must be taken immediately / #define KERN_CRIT KERN_SOH “2” / critical conditions / #define KERN_ERR KERN_SOH “3” / error conditions / #define KERN_WARNING KERN_SOH “4” / warning conditions / #define KERN_NOTICE KERN_SOH “5” / normal but significant condition / #define KERN_INFO KERN_SOH “6” / informational / #define KERN_DEBUG KERN_SOH “7” / debug-level messages */