【问题标题】:How to wisely interpret this compiler warning?如何明智地解释这个编译器警告?
【发布时间】:2018-12-06 01:24:59
【问题描述】:

当我执行这个question的代码时,我得到了这个警告:

warning: format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]
printf("P-Q: %d, P: %d, Q: %d", (p - q), p, q);
             ~^                 ~~~~~~~
             %ld

作为反射修复,我使用%ld 打印两个指针的减法。编译器同意了。

幸运的是,我看到另一个用户的评论提到应该使用%td,因为减法的结果类型是ptrdiff_t。这个answer 证实了这一说法。

现在从 GCC 的 stddef.h 头文件中,我可以看到在这种情况下这些类型是等价的:

typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int

但是,我只是建议对 OP 进行错误(或多或少)修复,使用 %ld,而不是 %td

有没有办法让我理解仅仅编译器警告是不够的?或者也许明智地解释了警告本身,而不仅仅是做出反应。

【问题讨论】:

  • 似乎是 QoI 问题。编译器应该能够检测到它被减去的两个指针,并打印 ptrdiff_t 而不是它的别名。
  • g++(如果用它编译也有意义的话)和 gcc 都提供了相同的警告@StoryTeller,如果有帮助的话。
  • 生活和学习。我还没有看到提及%ju%zu%tu 的编译器警告。警告总是提到实现使用的基本类型。所以你只需要知道...
  • Clang 也建议%ld...
  • user3386109 体验确定。智慧与经验同行..很高兴知道@Bob__,谢谢!

标签: c pointers types compiler-warnings pointer-arithmetic


【解决方案1】:

这里的关键是:首先不要在printf 中进行任何形式的算术运算。将算法与 GUI 分开。

printf("%d", p - q) 之类的代码非常危险,不仅因为您可能会在逻辑上弄错类型,还因为 C 可能会“帮您一个忙”并通过隐式类型提升默默地更改类型。 Examples.

此外,大多数编译器不会对错误的格式说明符发出警告。这是 C 历史上相对较新的事情,因为编译器不需要在此处显示诊断消息。这只是 gcc 的一个额外功能。

如何避免错误?这些功能本质上是危险的——就是这样,每个人都知道。就对人类造成的总错误成本而言,printf 和 scanf 系列函数可能是编程史上最有害的函数。那么你应该怎么做:

  • 尽可能避免使用stdio.h,并使其远离生产质量代码。可移植性并不总是比健壮的代码更重要——有时最好使用原始控制台 API。一般避免使用可变参数列表函数。
  • 如果无法避免,请将stdio.h 的“GUI”部分包装在一个单独的文件中,无论如何您都应该这样做。不要将打印/输入与算法混为一谈。制作一个使用指针的接口。
  • 现在是 2018 年,而不是 1970 年:首先不要编写控制台界面。是的,我知道......还有很多旧垃圾仍然漂浮在周围,需要维护。但是现在,控制台函数应该主要用于调试目的和学习 C 的新手,在这种情况下,类型安全可能不是那么大的问题。

【讨论】:

    【解决方案2】:

    我觉得你说不出来。这取决于编译器编写者的意图/谨慎/聪明。

    也许他决定始终支持%ld,而%td 是预期的,或者他只是不知道/无法/不愿意提供更详细/适当的信息。如有疑问,您的最后手段就是标准。

    这似乎不是一个可移植的构造,对于“正统”,您应该同时支持两种格式说明符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多