-Werror = format:编译器如何知道

时间:2013-12-06 13:04:02

标签: c++ c compiler-construction libc

我写了这个故意错误的代码

printf("%d %d", 1);

使用g++-Werror=format进行编译。

编译器给出了令人印象深刻的警告:

error: format '%d' expects a matching 'int' argument [-Werror=format]

据我所知,编译器无法判断代码是错误的,因为格式字符串不会被解析直到运行时。

我的问题:编译器是否有一个特殊功能可以用于printf和类似的libc函数,或者这是一个我可以用于我自己的函数的功能?字符串文字?

2 个答案:

答案 0 :(得分:10)

  

据我所知,编译器无法判断代码是错误的,因为格式字符串直到运行时才被解析。

只要格式字符串是字符串文字,就可以在编译时解析它。如果不是(这通常是个坏主意),那么您可以从-Wformat-security收到有关该问题的警告。

  

编译器是否有一个特殊功能可以启动printf和类似的libc函数?

  

或者这是我可以用于自己的功能的功能吗?

是的,只要您使用与printf相同格式的字符串(或scanfstrftime等各种其他标准函数)。

void my_printf(Something, char const * format, SomethingElse, ...)
    __attribute__ ((format (printf,2,4)));

表示第二个参数是printf - 样式格式字符串,格式值以第四个开头。请参阅http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

答案 1 :(得分:5)

好吧,printf肯定会在运行时解析格式字符串以完成其工作。但是,如果它想要,编译器可能不会选择自己解析它。

-Wformat的文档说明这正是发生的事情:

  

-Wformat

     

-Wformat=n

     

检查对printfscanf等的来电,以确保所提供的参数具有>适合格式字符串的类型   指定,以及格式字符串中指定的转换   合理。这包括标准功能,以及其他指定的功能   格式属性(请参阅函数属性),在printfscanf中,   strftimestrfmon(X / Open扩展,不在C标准中)   家庭(或其他针对特定目标的家庭)。哪些功能   检查没有指定格式属性取决于   选择标准版本,并且没有这样的功能检查   指定的属性已由-ffreestanding-fno-builtin停用。

     

根据GNU libc 2.2版支持的格式功能检查格式。   这些包括所有ISO C90和C99功能   以及单Unix规范和一些BSD和   GNU扩展。其他库实现可能不支持所有   这些功能; GCC不支持有关功能的警告   超出特定图书馆的限制。但是,如果-Wpedantic是   与-Wformat一起使用时,会给出关于不在的格式功能的警告   选定的标准版本(但不适用于strfmon格式,因为   那些不是任何版本的C标准)。请参阅选项   控制C语言。

更新:原来可以在您自己的功能上使用它。迈克有details