问题描述
typedef enum overrideType
{
ovrBool,ovrFloat,ovrUint32,} overrideType_t;
int override_New(const char name[],overrideType_t type,...);
我希望可选参数列表至少包含一项(如果我能保证它只包含一项就更好了)。是否也可以强加一组允许的类型?
基本上我希望能够编写以下说明:
override_New("a",ovrBool,true);
override_New("b",4.0f);
override_New("c",5,"string"); /* this is tolerable but if it were possible to have a warning would be better */
override_New("d",ovrFloat);
我对带有 gcc 扩展、属性、使用预处理器功能等的 C11 很好。
解决方法
相反,您的枚举对类型使用标准 printf 格式。然后 gcc 扩展 __attribute__((format(....)))
会警告你。
extern int override_New (const char name[],const char *fmt,...)
__attribute__ ((format (printf,2,3)));
void foo()
{
override_New("name","%s");
}
<source>: In function 'foo':
<source>:12:28: warning: format '%s' expects a matching 'char *' argument [-Wformat=]
12 | override_New("name","%s");
| ~^
| |
| char *
Compiler returned: 0
作为奖励,它还会检查类型。
,如果传递的参数少于 3 个,则可以使用预处理器 (__VA_ARGS__
):
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef enum overrideType
{
ovrBool,ovrFloat,ovrUint32,} overrideType_t;
#define override_New(a,b,...) override_New(a,__VA_ARGS__)
static int (override_New)(const char name[],overrideType_t type,...)
{
(void)name;
(void)type;
return 0;
}
int main(void)
{
override_New("a",ovrBool,true); // Ok
override_New("a",ovrBool); // Error
return 0;
}
然后,它会编译失败:
demo.c:23:30: warning: ISO C99 requires at least one argument for the "..." in a variadic macro
23 | override_New("a",ovrBool); // fail
| ^
demo.c:12:63: error: expected expression before ‘)’ token
12 | #define override_New(a,__VA_ARGS__)
| ^
demo.c:23:5: note: in expansion of macro ‘override_New’
23 | override_New("a",ovrBool); // fail
| ^~~~~~~~~~~~
demo.c:24:5: note: in expansion of macro ‘override_New’
24 | override_New("a",ovrBool); // fail
(override_New)
周围的括号阻止预处理器扩展函数定义,并允许您对宏和函数本身使用相同的名称。
如果您想要警告而不是错误,请使用 #__VA_ARGS__
gcc
扩展名:
#define override_New(a,#__VA_ARGS__)
返回:
demo.c:23:30: warning: ISO C99 requires at least one argument for the "..." in a variadic macro
23 | override_New("a",ovrBool); // fail
| ^
但它可以编译。
无论如何,最好完全避免可变参数,让编译器完成工作并使用 union
和复合文字:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef enum overrideType
{
ovrBool,} overrideType_t;
typedef union overrideValue
{
bool as_bool;
float as_float;
unsigned as_uint;
} overrideValue_t;
int override_New(const char name[],overrideValue_t value)
{
(void)name;
(void)type;
(void)value;
return 0;
}
int main(void)
{
override_New("a",(overrideValue_t){true}); // Ok
override_New("a",(overrideValue_t){true},"extra"); // Error
override_New("a",ovrBool); // Error
return 0;
}
返回:
demo.c:30:5: error: too many arguments to function ‘override_New’
30 | override_New("a","extra"); // Error
| ^~~~~~~~~~~~
demo.c:19:6: note: declared here
19 | int (override_New)(const char name[],overrideValue_t value)
| ^~~~~~~~~~~~
demo.c:31:5: error: too few arguments to function ‘override_New’
31 | override_New("a",ovrBool); // Error
| ^~~~~~~~~~~~
demo.c:19:6: note: declared here
19 | int (override_New)(const char name[],overrideValue_t value)
|