1

在 C 中,我想创建一个如下所示的函数或宏:

void Log(char* what, ...) 

其中 ... 必须是 const char* 的键值对。我真的希望不遵循此规则的代码在编译时爆炸。我尝试寻找执行此操作的 __attribute((..)) 指令,但无济于事。有任何想法吗?

4

3 回答 3

3

C 无法对任意可变参数强制执行类型安全。GCC 和 Clang__attribute__对于某些固定情况有 s(当可变参数函数期望最后一个参数是NULL时,您可以使用__sentinel__;或者当它是格式字符串时,您可以使用format),但是没有通用的解决方案。

另一方面,C++11 有可变参数模板来解决这个问题,但既然你提到你在用 C 工作,它就不适合你。

于 2014-01-22T22:49:51.850 回答
2

其中 ... 必须是 const char* 的键值对

那么你根本不需要可变参数。如果你事先知道你期望的类型,那么你就不需要它,你只是让事情变得比他们需要的更困难。

只需传入一个数组。

void Log(const char *what, const char **args, size_t size);
于 2014-01-22T23:11:28.433 回答
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 文字字符串而不是(@“...”而不是“...”),这是我之前的问题。

于 2014-01-23T01:53:46.497 回答