C++ GCC:_属性__((格式(printf,x,y))在使用可变宏调用函数时似乎不起作用

C++ GCC:_属性__((格式(printf,x,y))在使用可变宏调用函数时似乎不起作用,c++,c,gcc,macros,variadic,C++,C,Gcc,Macros,Variadic,GCC版本ntoarm GCC(GCC)4.4.2 我已经为所有包装printf()和co的函数添加了“printf”格式属性。除了使用可变宏调用函数外,它们工作得非常好 class Log { [...] void log_fmt(LogLevel level, const std::string& funcName, const char_t * const logFormatStr, ...) __attribute__ ((format (printf, 4, 5)))

GCC版本ntoarm GCC(GCC)4.4.2

我已经为所有包装printf()和co的函数添加了“printf”格式属性。除了使用可变宏调用函数外,它们工作得非常好

class Log { [...]
    void log_fmt(LogLevel level, const std::string& funcName, const char_t * const logFormatStr, ...)  __attribute__ ((format (printf, 4, 5)));
[...] };
不正确的直接呼叫,如

log.log\u fmt(信息,“测试”,“错误的%u”,“类型”);

警告:

格式“%u”要求类型为“unsigned int”,但参数5的类型为“const char*”

使用宏的相同错误调用不会产生警告,但是:

#define LOGI(MSG, ...) log.log_fmt(Info, __func__, (MSG), __VA_ARGS__)
LOGI("wrong %u", "type");
我能在这种情况下也显示警告吗?我是否犯了错误,或者这是故意的行为?

这:

#include <iostream>
#include <cstdio>

struct log {
    static void logf(std::string, std::string, const char*, ...) __attribute__((format (printf, 3, 4))) {}
};

#define L(m, ...) log::logf("no", __func__, (m), __VA_ARGS__)

int main() {
    //log::logf("hi", "hi", "test %u", "hi");
    L("test %u", "hi");
}

因此,我猜问题出在位置参数上(您在
format
属性上放置了
4,5
,而您似乎应该放置
3,4
)..

宏不检查类型。它们只是回答您是否尝试了
-Wall
-Wextra
参数到
gcc
4,5在初始代码中是正确的。请注意,您的宏是作为静态成员函数实现的,而原始宏调用了日志对象的成员函数,该函数添加了隐藏的
参数。尽管如此,该构造也适用于非静态成员函数。@unbekannt:我只能假设您设法以某种方式对调用代码隐藏了format属性(多个包含文件,其中一个缺少
format
函数属性?)@mfro,你对
4,5
的看法完全正确。但是它仍然非常有效(给我一个警告),看……受马萨回答的启发,我尝试用一个简单的例子让它再次工作。它确实有效。它在“真实”中继续工作代码。当这种情况发生时,我多么讨厌它……看起来我确实犯了一些愚蠢的错误。接受马萨斯的回答可以吗,因为这会让我再次尝试?
main.cpp: In function 'int main()':
main.cpp:8:61: warning: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'const char*' [-Wformat=]
 #define L(m, ...) log::logf("no", __func__, (m), __VA_ARGS__)
                                                             ^
main.cpp:12:5: note: in expansion of macro 'L'
     L("test %u", "hi");
     ^
At global scope:
cc1plus: warning: unrecognized command line option "-Wno-undefined-internal" [enabled by default]