在 C 中,我想创建一个如下所示的函数或宏:
void Log(char* what, ...)
其中 ... 必须是 const char* 的键值对。我真的希望不遵循此规则的代码在编译时爆炸。我尝试寻找执行此操作的 __attribute((..)) 指令,但无济于事。有任何想法吗?
在 C 中,我想创建一个如下所示的函数或宏:
void Log(char* what, ...)
其中 ... 必须是 const char* 的键值对。我真的希望不遵循此规则的代码在编译时爆炸。我尝试寻找执行此操作的 __attribute((..)) 指令,但无济于事。有任何想法吗?
C 无法对任意可变参数强制执行类型安全。GCC 和 Clang__attribute__
对于某些固定情况有 s(当可变参数函数期望最后一个参数是NULL
时,您可以使用__sentinel__
;或者当它是格式字符串时,您可以使用format
),但是没有通用的解决方案。
另一方面,C++11 有可变参数模板来解决这个问题,但既然你提到你在用 C 工作,它就不适合你。
其中 ... 必须是 const char* 的键值对
那么你根本不需要可变参数。如果你事先知道你期望的类型,那么你就不需要它,你只是让事情变得比他们需要的更困难。
只需传入一个数组。
void Log(const char *what, const char **args, size_t size);
好的,我想出了一个解决方法:
#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 文字字符串而不是(@“...”而不是“...”),这是我之前的问题。