C __函数指针上的属性

C __函数指针上的属性,c,clang,C,Clang,有时出于各种原因,我会围绕printf风格的函数编写包装,我非常喜欢让clang告诉我格式说明符和实际参数之间的类型不匹配。考虑: #包括 #包括 静态属性(格式(printf,1,2)))无效日志(const char*fmt,…) { va_列表va; va_启动(va,fmt); vprintf(fmt,va); va_端(va); } 内部主(空) { 日志(“%s”,42); 返回0; } 如果使用-Wall编译,它会清楚地通知我该类型错误: test.c:14:15:warning

有时出于各种原因,我会围绕printf风格的函数编写包装,我非常喜欢让clang告诉我格式说明符和实际参数之间的类型不匹配。考虑:

#包括
#包括
静态属性(格式(printf,1,2)))无效日志(const char*fmt,…)
{
va_列表va;
va_启动(va,fmt);
vprintf(fmt,va);
va_端(va);
}
内部主(空)
{
日志(“%s”,42);
返回0;
}
如果使用
-Wall
编译,它会清楚地通知我该类型错误:

test.c:14:15:warning:format指定类型“char*”,但参数的类型为“int”[-Wformat]
日志(“%s”,42);
~~   ^~
%d
这对于函数来说非常有效,但对于函数指针,
\uuuuu属性(format(printf,1,2))
似乎不再有效。以下代码:

#包括
#包括
typedef void(*log_t)(常量字符*,…)__属性(格式(printf,1,2));
静态属性(格式(printf,1,2)))无效日志(const char*fmt,…)
{
va_列表va;
va_启动(va,fmt);
vprintf(fmt,va);
va_端(va);
}
内部主(空)
{
log\u t func=&log;
(*func)(“%s”,42);
返回0;
}
编译时在
-Wall
下没有警告,但生成的程序会出错。我试着在typedef的每个部分都添加属性说明符,但似乎没有什么不同

是否有一种方法可以使用clang为函数指针指定属性(或此属性),以便在编译过程中实际拾取它?

如果重要的话,my clang会将其版本报告为:
Apple LLVM 9.0.0版(clang-900.0.39.2)

将属性说明符与指针声明放在同一行会起作用(即,导致对不匹配的参数发出警告)

因此,如果目标是最小化键入并保持代码整洁,那么我认为您必须使用宏。大概是这样的:

#define checkargs __attribute__((format(printf, 1, 2)))

typedef void (*log_t)(const char*, ...);

static checkargs void log(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    vprintf(fmt, va);
    va_end(va);
}

int main(void)
{
    log_t checkargs func = log;
    func("%s", 42);
}

有趣的是,将调用更改为
(*func)(“%s”,42)似乎打破了这个。。。尽管如此,我仍然可以使用一个解决方案。:)@西格扎:嗯,奇怪。但只要它对您有效,这就是最重要的:)如果您使用的是宏,为什么不使用
static checkargs void log(…){…}
#define checkargs __attribute__((format(printf, 1, 2)))

typedef void (*log_t)(const char*, ...);

static checkargs void log(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    vprintf(fmt, va);
    va_end(va);
}

int main(void)
{
    log_t checkargs func = log;
    func("%s", 42);
}