如何明智地解释此编译器警告?

时间:2018-06-27 08:17:50

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

当我执行此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_tanswer证实了这一主张。

现在从stddef.h的GCC头文件来看,在这种情况下,这些类型是等效的:

typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int

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

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

2 个答案:

答案 0 :(得分:2)

我认为你看不出来。这取决于编译器编写者的意图/谨慎/聪明。

也许他决定在期望ExponentialReconnectionPolicy的情况下总是支持%ld,或者他只是不知道/无法/不愿意给出更详细/正确的信息。如有疑问,您的最后选择就是标准。

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

答案 1 :(得分:2)

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

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

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

如何避免错误?这些功能本质上是危险的-事实就是如此,而且每个人都知道。就人类造成的总错误成本而言,可能的printf和scanf函数族是有史以来编程中最有害的函数。所以你应该怎么做:

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