__attribute__函数指针

时间:2018-06-13 01:12:16

标签: c clang

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

#include <stdarg.h>
#include <stdio.h>

static __attribute__((format(printf, 1, 2))) void log(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    vprintf(fmt, va);
    va_end(va);
}

int main(void)
{
    log("%s", 42);
    return 0;
}

如果使用-Wall编译,它会巧妙地告诉我类型错误:

test.c:14:15: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
    log("%s", 42);
         ~~   ^~
         %d

这对函数非常有效,但是当涉及函数指针时,__attribute__((format(printf, 1, 2)))似乎不再有效。以下代码:

#include <stdarg.h>
#include <stdio.h>

typedef void (*log_t)(const char*, ...) __attribute__((format(printf, 1, 2)));

static __attribute__((format(printf, 1, 2))) void log(const char *fmt, ...)
{
    va_list va;
    va_start(va, fmt);
    vprintf(fmt, va);
    va_end(va);
}

int main(void)
{
    log_t func = &log;
    (*func)("%s", 42);
    return 0;
}

-Wall下编译时没有警告,但产生的程序会出现段错误。我尝试将属性说明符放在typedef的每个部分中,但它似乎没有什么区别。

有没有办法让clang为函数指针指定属性(或 this 属性),以便在编译时实际拾取它?
如果重要,我的clang将其版本报告为:Apple LLVM version 9.0.0 (clang-900.0.39.2)

1 个答案:

答案 0 :(得分:2)

将属性说明符放在带有指针声明的行上(即产生关于不匹配参数的警告)

log_t func __attribute__((format(printf, 1, 2))) = 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);
}