如何保证可变参数的类型安全性?

时间:2014-01-22 22:45:31

标签: c variadic-functions variadic-macros

在C中,我想制作一个看起来像这样的函数或宏:

void Log(char* what, ...) 

其中...必须是const char *的键值对。我真的很喜欢在编译时没有遵循这个问题的代码。我尝试寻找一个执行此操作的__attribute((..))指令,但无济于事。有什么想法吗?

3 个答案:

答案 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文字字符串(@“...”而不是“...”),这就是我之前的事。