【问题标题】:-Werror=format: how can the compiler know-Werror=format:编译器怎么知道
【发布时间】:2013-12-06 13:04:01
【问题描述】:

我故意写错了代码

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

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

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

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

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

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

【问题讨论】:

  • “因为格式字符串直到运行时才被解析”你确定吗?这很有趣,如果这是真的。留在运行时对我来说没有意义。
  • 编译器不做神奇的代码分析。它对printf 和类似的libc 函数进行特殊情况检查。它不会自动与您自己的函数一起使用。

标签: c++ c compiler-construction libc


【解决方案1】:

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

只要格式字符串是字符串字面量,就可以在编译时解析。如果不是(无论如何这通常是个坏主意),那么您可以从-Wformat-security 收到关于此的警告。

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

是的。

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

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

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

表示第二个参数是printf-style 格式字符串,并且要格式化的值从第四个开始。见http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

【讨论】:

  • 这个__attibute__ 非常有用。 Clang 和 MSVC++ 有相似之处吗?
  • @user3001464:Clang 具有与 GCC 相同的属性。我从不使用微软的编译器,但this question 似乎表明有类似的东西。
【解决方案2】:

好吧,printf 肯定会在运行时解析格式字符串以完成其工作。但是没有任何地方写到编译器可以不选择自己解析它。

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

-Wformat

-Wformat=n

检查对printfscanf 等的调用,以确保提供的参数具有> 适合格式字符串的类型 指定的,以及格式字符串中指定的转换 有道理。这包括标准功能,以及由 格式属性(参见函数属性),在printfscanfstrftimestrfmon(X/Open 扩展,不在 C 标准中) 家庭(或其他特定于目标的家庭)。有哪些功能 在没有指定格式属性的情况下检查取决于 选择了标准版本,并且这种功能检查没有 指定的属性被-ffreestanding-fno-builtin 禁用。

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

更新:原来你可以在你自己的函数中使用它。迈克有details

【讨论】:

  • 关于将此功能用于您自己的功能:您可以也不能。您可以为自己的函数指定format 属性,但您必须指定它使用哪种标准格式字符串;你不能发明全新的东西。
  • @JamesKanze:谢谢,我不知道。
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多