在C中,我想制作一个看起来像这样的函数或宏:
void Log(char* what, ...)
其中...必须是const char *的键值对。我真的很喜欢在编译时没有遵循这个问题的代码。我尝试寻找一个执行此操作的__attribute((..))指令,但无济于事。有什么想法吗?
答案 0 :(得分:3)
C无法对任意可变参数进行类型安全性强制执行。对于某些固定的情况,GCC和Clang有__attribute__
个(当一个可变函数期望最后一个参数为NULL
时,你可以使用__sentinel__
;或者当它是一个格式字符串时,你可以使用format
),但没有通用解决方案。
另一方面,C ++ 11有可变模板来解决这个问题,但是既然你提到你在C中工作,它就不适合你了。
答案 1 :(得分:2)
其中......必须是const char *的键值对
然后你根本不需要可变参数。如果你事先知道你期望的类型,那么你就不需要它,而你只是让事情变得比他们需要的更困难。
只需传入数组。
void Log(const char *what, const char **args, size_t size);
答案 2 :(得分:1)
好的,我想出了一个解决方法:
#define ASSERT_LIST_TYPE(t, l...) do{t _t[] = {l};}while(0)
void _Log(char* what, ...);
#define Log(what, args...) do{\
ASSERT_LIST_TYPE(char*, args);\
_Log(what, args);\
}while(0)
如果args的类型不正确,至少会产生警告,因为虚拟数组初始化的类型不正确。
如果这不是调试版本,我计划#ifdef'ing ASSERT_LIST_TYPE以防万一..
**编辑**
根据此处的反馈,我将代码更改为:
void _Log(char* what, const char** args, size_t args_len);
#define Log(what, args...) do{\
const char* a[] = {args};\
_Log(what, a, (sizeof a)/sizeof(char*));
}while(0)
即使args是空的,它似乎也可以工作,并且它会捕获某人传递一个obj-c文字字符串(@“...”而不是“...”),这就是我之前的事。