Python 3.8以上的版本支持f字符串
的变量打印功能1,比如:
num = 42
print(f'{num=}')
输出得到:
num=42
这样的方法提高了调试效率。
我觉得这个方法不错,利用C语言的宏定义#var
可以将变量转化为字符串,实现类似的效果:
#if LINE_NUMBER
#define LN printf("(ln: %3d) ", __LINE__)
#else
#define LN 0
#endif
#define puts(s) LN + printf("%s\n", s)
#define log_str(x) LN + printf(#x"=\"%s\"\n", x)
#define log_num(x) LN + printf(#x"=%g\n", (float)x)
打印的效果类似如下:
(ln: 7) start!
(ln: 10) s="Hello!"
(ln: 15) n1=1024
(ln: 16) n2=3.14
其中printf
函数返回值是int
类型,所以可以利用两个printf
函数相加,实现在一次printf
后再printf
一次,通过开关宏定义LINE_NUMBER
设置是否打印行号。
如果C语言支持C11标准,支持_Generic
关键词,还可以将数字、或字符串用同一个宏定义函数打印2。参考代码如下:
#include
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define u64 unsigned long long
#define s8 signed char
#define s16 signed short
#define s32 signed int
#define s64 signed long long
void log_int(const char* name, int value) {
printf("%s=%d\n", name, value);
}
void log_float(const char* name, float value) {
printf("%s=%g\n", name, value);
}
void log_str(const char* name, void* value) {
printf("%s=\"%s\"\n", name, value);
}
#define log(x) _Generic((x)\
,u8 : log_int\
,u16 : log_int\
,u32 : log_int\
,s8 : log_int\
,s16 : log_int\
,s32 : log_int\
,float : log_float\
,double: log_float\
,u8* : log_str\
,s8* : log_str\
,char* : log_str\
)(#x, x)
void main() {
int n1 = -114;
float n2 = 5.14;
char s1[] = "hello";
log(n1);
log(n2);
log(s1);
}
有时候在嵌入式平台上,printf
打印需要重定向到串口输出。如果遇到不能使用printf
打印,可以使用一种替代的解决方法:
#include
#include
#include
#define PRINT_TO_SCREEN 1
#define PRINT_TO_STRING 1
#define PRINT_TO_FILE 1
#define printf log_print
char log_buff[0x100000]; // 1MB
char *log_pbuff = log_buff;
int log_reset = 1;
int log_print(char* format, ...)
{
va_list p;
va_start(p, format);
#if PRINT_TO_SCREEN
vprintf(format, p);
#endif
#if PRINT_TO_STRING
vsprintf(log_pbuff, format, p);
log_pbuff = strchr(log_pbuff, 0);
#endif
#if PRINT_TO_FILE
FILE *fp = fopen("log.txt", log_reset ? "w+" : "a+");
log_reset = 0;
vfprintf(fp, format, p);
fclose(fp);
#endif
va_end(p);
return 0;
}
通过将printf
重定向到log_print
函数,使用原有的printf
就可以可选地将内容打印到屏幕、字符串、和本地文件。
通过初始化全局变量log_reset
是否等于1,可以设置每次重启程序前是否清空之前记录文件。
使用方法参考:
printf("k=%d\n", 114);
printf("y=%d\n", 514);
运行结束后再次查看buf
,字符串会变得丰富:
"k=114\ny=514\n"
需要注意的是,总打印的字符长度不要超过buf
申请的空间长度,例如本示例中申请的0x100000
是1MB
空间大小。
本方法前面的宏定义打印参数名+参数值两者互相不冲突,可以同时使用。
我将代码整理成了头文件的形式,现在可以通过添加头文件,将调试函数加入代码,在代码一开头加入:
#include "log.h"
就可以使用头文件里面的函数了。文件下载地址:
https://download.csdn.net/download/weixin_39804265/87241255