我有一个宏来做一个默认参数的版本:
#define Log_getMacro4(_1, _2, _3, _4, NAME, ...) NAME
#define Log_logWarning4(...) Log_log__("warning", __VA_ARGS__)
#define Log_logWarning3(...) Log_log__("warning", __VA_ARGS__, __LINE__)
#define Log_logWarning2(...) Log_log__("warning", __VA_ARGS__, __FILE__, __LINE__)
#define Log_logWarning1(...) Log_log__("warning", __VA_ARGS__, __PRETTY_FUNCTION__, __FILE__, __LINE__)
#define Log_logWarning(...) Log_getMacro4(__VA_ARGS__, Log_logWarning4, Log_logWarning3, Log_logWarning2, Log_logWarning1)(__VA_ARGS__)
问题是我现在想要在该函数上提供一个变体,它在第一个参数之后释放Log_logWarning:
#define Log_logWarning_free(str, ...) Log_logWarning(str, __VA_ARGS__); if (str) free(str);
问题是这不能与函数的返回值一起使用。例如:
char *foo(){
char *ret = (char*)malloc(30*sizeof(char));
strcpy(ret, "Hello World");
return ret;
}
void bar(){
Log_logWarning_free(foo());
}
因此,我想知道是否有办法首先创建一个局部变量,我将为其分配宏的第一个参数,然后在测试中使用该变量,随后将其释放。
答案 0 :(得分:2)
如果可能,我会使用内联函数。
如果必须使用宏,请使用do { ... } while (0)
构造:
#define Log_logWarning_free(str, ...) \
do { \
char * logtmp_ = str; \
Log_logWarning(logtmp_, __VA_ARGS__); \
if (logtmp_) free(logtmp_); \
} while (0)
do-while-0 trick允许您拥有代码块,同时防止意外地将块意外地附加到另一个流控制结构。
这个完整的测试程序编译为4.7.2:
#include <stdlib.h>
#define Log_logWarning_free(str, ...) \
do { \
char * logtmp_ = str; \
Log_logWarning(logtmp_, __VA_ARGS__); \
if (logtmp_) free(logtmp_); \
} while (0)
void Log_logWarning(char* fmt, ...);
char * get_log_str(void);
int main()
{
Log_logWarning_free(get_log_str(), 1, 2, 3);
return 0;
}
答案 1 :(得分:1)
首先,将您的函数包装在do { } while(0)
中,这样您就可以为函数的使用添加分号,避免出现奇怪的错误。
其次,是的,您可以使用局部变量。有关示例,请参阅http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html。
一个简单的例子是
#define swap(a,b) do {int _c=b; b=a; a=_c;} while(0)
然后可以安全地调用它:
int x = 5;
int y = 7;
swap(x, y);
答案 2 :(得分:1)
问题在于知道变量的类型(除了 C ++ 11)。对于其他人,您可以使用通常的技巧来确定范围:
#define X(y) do { auto CONCAT(_log_tmp_,__LINE__) = (y); ... } while(false);
在C和C ++前C ++ 11中,您可能必须传递该类型 变量作为宏的参数。