如何明智地解释这个编译器警告?
How to wisely interpret this compiler warning?
当我执行这个 的代码时,我收到了这个警告:
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
。这 证实了这一说法。
现在从stddef.h的GCC头文件中,我可以看出这些类型在这种情况下是等价的:
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int
但是,我只是想建议对 OP 进行错误的(或多或少)修复,使用 %ld
,而不是 %td
。
有什么方法可以让我明白仅靠编译器警告是不够的?或者也许明智地解释了警告本身,而不仅仅是做出反应。
我觉得你看不出来。这取决于编译器作者的intent/caution/smartness。
也许他决定他将永远支持 %ld
,而 %td
是预期的,或者他只是 unaware/unable/unwilling 给出了更多 detailed/proper 的信息。如有疑问,您的最后一招就是标准。
这似乎不是一个可移植的结构,对于 "orthodoxy" 你应该支持两种格式说明符。
这里的关键是:首先不要在 printf
中进行任何形式的算术运算。将算法与 GUI 分开。
printf("%d", p - q)
之类的代码非常危险,不仅因为您可能会在逻辑上弄错类型,还因为 C 可能 "do you a favour" 并通过隐式类型提升悄悄更改类型。 .
此外,大多数编译器不会对错误的格式说明符发出警告。这是 C 历史上相对较新的事物,因为编译器不需要在此处显示诊断消息。这只是 gcc 的一个额外功能。
如何避免错误?这些功能本质上是危险的——事实就是如此,每个人都知道这一点。就给人类造成的错误总成本而言,printf 和 scanf 函数族可能是编程史上最有害的函数。那么你应该怎么做:
- 尽可能避免
stdio.h
并使其远离生产质量代码。可移植性并不总是比健壮的代码更重要——有时最好使用原始控制台 API。通常避免使用可变参数列表函数。
- 如果无法避免,请将
stdio.h
的 "GUI" 部分包装在一个单独的文件中,无论如何您都应该这样做。不要将 printing/input 与算法混用。创建一个使用指针的接口。
- 现在是 2018 年,不是 1970 年:首先不要编写控制台界面。是的,我知道……有很多旧垃圾仍然漂浮在周围,需要维护。但是如今,控制台功能应该主要用于调试目的和学习 C 的新手,在这种情况下类型安全可能不是一个大问题。
当我执行这个
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
。这
现在从stddef.h的GCC头文件中,我可以看出这些类型在这种情况下是等价的:
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int
但是,我只是想建议对 OP 进行错误的(或多或少)修复,使用 %ld
,而不是 %td
。
有什么方法可以让我明白仅靠编译器警告是不够的?或者也许明智地解释了警告本身,而不仅仅是做出反应。
我觉得你看不出来。这取决于编译器作者的intent/caution/smartness。
也许他决定他将永远支持 %ld
,而 %td
是预期的,或者他只是 unaware/unable/unwilling 给出了更多 detailed/proper 的信息。如有疑问,您的最后一招就是标准。
这似乎不是一个可移植的结构,对于 "orthodoxy" 你应该支持两种格式说明符。
这里的关键是:首先不要在 printf
中进行任何形式的算术运算。将算法与 GUI 分开。
printf("%d", p - q)
之类的代码非常危险,不仅因为您可能会在逻辑上弄错类型,还因为 C 可能 "do you a favour" 并通过隐式类型提升悄悄更改类型。
此外,大多数编译器不会对错误的格式说明符发出警告。这是 C 历史上相对较新的事物,因为编译器不需要在此处显示诊断消息。这只是 gcc 的一个额外功能。
如何避免错误?这些功能本质上是危险的——事实就是如此,每个人都知道这一点。就给人类造成的错误总成本而言,printf 和 scanf 函数族可能是编程史上最有害的函数。那么你应该怎么做:
- 尽可能避免
stdio.h
并使其远离生产质量代码。可移植性并不总是比健壮的代码更重要——有时最好使用原始控制台 API。通常避免使用可变参数列表函数。 - 如果无法避免,请将
stdio.h
的 "GUI" 部分包装在一个单独的文件中,无论如何您都应该这样做。不要将 printing/input 与算法混用。创建一个使用指针的接口。 - 现在是 2018 年,不是 1970 年:首先不要编写控制台界面。是的,我知道……有很多旧垃圾仍然漂浮在周围,需要维护。但是如今,控制台功能应该主要用于调试目的和学习 C 的新手,在这种情况下类型安全可能不是一个大问题。