带参数的宏函数在预处理时,宏参数展开位置以“,”计数为基准。

为了兼容多种情况的log记录,写了一个参数比较多log记录函数宏。在应用时,又不想多定义一个变量,把结构体指针直接写在参数里,代码如下。

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#define LOG_LEN_MAX 128
#define LOG_PARA1 1
#define LOG_PARA2 2
#define VAL_TEST 3

typedef struct {
	int para1;
	int para2;
} LogPara;

#define LOG_TRACE(para, fmt, ...)  LogTrace(__FILE__, __LINE__, para, fmt, ##__VA_ARGS__)

int LogTrace(const char *file, int line, LogPara *para, const char *fmt, ...)
{

	char logStr[LOG_LEN_MAX] = {0};

	sprintf(logStr, "para %d %d, File: %s, Line: %d info: ", para->para1, para->para2, file, line);
	
	va_list args;
	va_start(args, fmt);
	vsprintf(logStr + strlen(logStr), fmt, args);
	va_end(args);

	printf("%s \n", logStr);

	return 0;
}

int main()
{
	int val = VAL_TEST;
	LOG_TRACE(&(LogPara){LOG_PARA1, LOG_PARA2}, "val is %d", val);

	return 0;
}

结果编译失败,原因时参数太少了。

从定义上看,参数数量没有问题,因为涉及宏展开,因此直接看预处理后的代码,命令和代码片段如下。

int main()
{
 int val = 3;
 LogTrace(&(LogPara){1, "macro.c", 37, 2}, "val is %d", val);

 return 0;
}

文件名和行数的宏直接插进结构体里面去了,从几次实验的结果看,所有的宏参数的位置都是按“,”的位置来插入的,__FILE__前面只有一个逗号,因此展开后插入到了第一个“,”后面。

解决的方法也比较简单,要么把结构体指针放在所有结构体外的宏参数的后面,要么加个括号,如下两种。

结构体放到后面

#define LOG_TRACE(para, fmt, ...)  LogTrace(__FILE__, __LINE__, para, fmt, ##__VA_ARGS__)

加个括号

int main()
{
	int val = VAL_TEST;
	LOG_TRACE((&(LogPara){LOG_PARA1, LOG_PARA2}), "val is %d", val);

	return 0;
}

GCC的代码没有研究过,看了一会也没看懂,如果有比较熟悉的大神也帮忙看看处理逻辑。个人认为都可以算GCC的小BUG了。

 gitcode链接:

GitCode - 全球开发者的开源社区,开源代码托管平台

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值