场景
当前遇到一个问题,有一个定义log输出的头文件,内容大致是这样的
#ifndef SWACK_COMMON_INCLUDE_SWACK_LOG_H_
#define SWACK_COMMON_INCLUDE_SWACK_LOG_H_
#define SWACK_LOG_LEVEL_DEBUG (1)
#define SWACK_LOG_LEVEL_ERROR (2)
#define SWACK_LOG_LEVEL_NONE (3)
#ifndef SWACK_LOG_LEVEL
#define SWACK_LOG_LEVEL SWACK_LOG_LEVEL_DEBUG
#endif
/* gcc on Linux */
#elif defined(__linux__)
#include
#include
#define MAX_LOG_SIZE 1024
#if (SWACK_LOG_LEVEL > SWACK_LOG_LEVEL_DEBUG)
#define LOGD(...)
#else
#define LOGD(...) \
{ \
printf(__VA_ARGS__); \
}
#endif
#if (SWACK_LOG_LEVEL > SWACK_LOG_LEVEL_ERROR)
#define LOGE(...)
#else
#define LOGE(...) { \
printf("LOGE (%s:%i) ",__func__,__LINE__); \
printf(__VA_ARGS__); \
}
#endif
/* TODO: Add LOGD/LOGE for other platforms */
#endif
#endif // SWACK_COMMON_INCLUDE_SWACK_LOG_H_
但是这里遇到一个问题:
如果我们定义了某个函数用于dump信息
void dump(void)
{
LOGD("111")
LOGD("222")
LOGD("333")
}
如果现在你把SWACK_LOG_LEVEL设置为3,此时不打印任何log
如果现在你把``你的项目对于代码编译有要求
add_compile_options(-g -fPIC -Wall -Wextra -Werror -pedantic -O3)
你会拿到一个错误:
error: unused parameter ‘buffer’ [-Werror=unused-parameter]
这个问题很显然,因为你现在不打印log了,那么dump函数为空的,它的哪些传输的变量啥也没做,所以会触发[-Werror=unused-parameter]
解决
出现错误的原因是,注销LOGD后,部分变量变成unused,所以我们需要把哪些参数used
解法一
一个最简单的方式,我们可以用sprintf
#define MAX_LOG_SIZE 1024
#define LOGD(...) \
{ \
char tmp_log[MAX_LOG_SIZE]; \
sprintf(tmp_log, __VA_ARGS__); \
}
解法二
这里很显然,只要用一下LOGD(...)后面的...,就能解决这个问题,所以以上源代码给出的方案是用sprintf来解决以上问题,但是这个解决方案显然很突兀,而且sprintf是会带来开销的
如果能把...直接void,那就太好了
在宏定义中,LOGD(...)传入的...,其实等效的等于__VA_ARGS__
所以可以类似方法解决
#define get1th_delay(a1, ...) a1
#define get2th_delay(a1, a2, ...) a2
#define get3th_delay(a1, a2, a3, ...) a3
#define get4th_delay(a1, a2, a3, a4, ...) a4
#define get5th_delay(a1, a2, a3, a4, a5, ...) a5
#define get6th_delay(a1, a2, a3, a4, a5, a6, ...) a6
#define get7th_delay(a1, a2, a3, a4, a5, a6, a7, ...) a7
#define get8th_delay(a1, a2, a3, a4, a5, a6, a7, a8, ...) a8
#define get9th_delay(a1, a2, a3, a4, a5, a6, a7, a8, a9, ...) a9
#define get10th_delay(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
#define leftBracket (
#define eatComma(...) , ##__VA_ARGS__
#define get1th(...) get1th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get2th(...) get2th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get3th(...) get3th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get4th(...) get4th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get5th(...) get5th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get6th(...) get6th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get7th(...) get7th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get8th(...) get8th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define get9th(...) get9th_delay(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
//#define parameterNum(...) get9th_delay leftBracket eatComma(__VA_ARGS__), 8,
// 7, 6, 5, 4, 3, 2, 1)
#define parameterNum(...) \
get10th_delay(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define LOGD(...) \
{ \
switch (parameterNum(__VA_ARGS__)) \
{ \
case 1: \
(void)(get1th(__VA_ARGS__)); \
break; \
case 2: \
(void)(get1th(__VA_ARGS__)); \
(void)(get2th(__VA_ARGS__)); \
break; \
case 3: \
(void)(get1th(__VA_ARGS__)); \
(void)(get2th(__VA_ARGS__)); \
(void)(get3th(__VA_ARGS__)); \
break; \
case 4: \
(void)(get1th(__VA_ARGS__)); \
(void)(get2th(__VA_ARGS__)); \
(void)(get3th(__VA_ARGS__)); \
(void)(get4th(__VA_ARGS__)); \
break; \
case 5: \
(void)(get1th(__VA_ARGS__)); \
(void)(get2th(__VA_ARGS__)); \
(void)(get3th(__VA_ARGS__)); \
(void)(get4th(__VA_ARGS__)); \
(void)(get5th(__VA_ARGS__)); \
break; \
} \
}
解法三
换一个思路,可以借助stdarg.h
首先了解下stdarg.h,主要包含以下宏定义
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )
然后我们利用他的特性
#ifdef __cplusplus
extern "C" {
#endif
static inline void void_log(char* fmt, ...)
{
(void)fmt;
va_list args;
va_start(args, fmt);
va_end(args);
}
#ifdef __cplusplus
}
#endif
#define LOGD(...) void_log(__VA_ARGS__)