[Day7] 简单的Log

昨天做输出系统的时候,发现输出Vector2这样常见的结构,没有一个通用的函式直接转成字串。再往回看,好像没有做过Log功能欸,虽然直接使用printf也可以,但既然都要重头开始了,那就做出一个简单的log功能吧~!

今日目标

  • Log功能

先来看看printf

int printf( const char* format, ... )

最开始学的时候就很好奇,为什麽C语言的功能很简单(相对其他语言),但printf可以带这麽多参数进去,之前没想那麽多,想说能用就好了,今天就趁这个机会来解析一下到底是做了甚麽,而这个秘密就在那个...里面。

那个叫做Variadic functions(我不知道中文怎麽翻),它可以让我们N个参数,那要怎麽让函式变成可以有N个参数呢?答案就在stdarg.h的脚本里面。

其中:

  • va_list: 是储存任意复数结构的一个list
  • va_start: 第一个参数表示cursor从哪个参数开始,他会往下读
  • va_end: 最後用完va_list要自己回收

之後就可以用这三个,写出一个极简单的Log功能

void LogMessage(LogT log_type, const char* file_name, int line, const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);

    fprintf(stdout, "%s %s:%d ", LOG_LABELS[log_type], file_name, line);
    vfprintf(stdout, fmt, args);
    fprintf(stdout, "\n");

    va_end(args);
}

上面的va_start就等於是,从参数列fmt开始,读後面开始的任意得参数。

可以看到着函式还要印出「哪个文件」和「第几行开始」,这就可以简单的用上C语言内建的marco:

 __FILE__、__LINE__

直接把相对的把这个功能做出来。

然後再依靠LogMessage,改成macro function,最後就可以做出不同阶级的log罗

#define LogInfo(...) LogMessage(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__);
#define LogWarning(...) LogMessage(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__);
#define LogError(...) LogMessage(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__);

至於macro function中的...跟__VA_ARGS__(注意: 是两条底线喔),是甚麽呢?
__VA_ARGS__是个macro,等於这个函式任意任数量的参数,简单来说,上面的code就表示

... == (const char* fmt, ...)

参考

最後这是今天的成果


<<:  Day3:如何加速将同步到Azure Active Directory的使用者移除

>>:  < 关於 Next: 开始打地基| CSS的引入方式 >

如何让 IIS 底下的 PHP 显示错误内容 (500 Error)

今天在IIS上安装的PHP发生了错误,可是一直出现 500-内部服务器错误,这样会看不到正确的错误内...

Lifecycle

今天要介绍的是Vue生命周期的四个阶段,先来看一张官网中Vue的生命周期图吧! 首先当然是要建立一个...

[Day8]-元组(tuple)

基本元组 元组的结构跟串列是一样的,但元组可以更安全的保护资料,因为它的资料不会被改变,而且元组的...

D04 / 可不可以用 ConstraintLayout - ConstraintLayout

今天大概会聊到的范围 Constraint Layout in Compose 上一篇提到,有 R...

【心得】Sublime TexT 3 即时连线

一开始学习时用Sublime,久了之後也成为一种习惯(,,・ω・,,) 但是初学者很喜欢写一步骤就要...