当我执行此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证实了这一主张。
现在从stddef.h的GCC头文件来看,在这种情况下,这些类型是等效的:
typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int
但是,我只是建议使用%ld
而不是%td
对OP进行错误的(或多或少)修复。
有没有一种方法可以理解仅编译器警告是不够的?或者,也许是明智地解释了警告本身,而不仅仅是做出了反应。
答案 0 :(得分:2)
我认为你看不出来。这取决于编译器编写者的意图/谨慎/聪明。
也许他决定在期望ExponentialReconnectionPolicy
的情况下总是支持%ld
,或者他只是不知道/无法/不愿意给出更详细/正确的信息。如有疑问,您的最后选择就是标准。
这似乎不是可移植的结构,对于“正统”,您应该同时支持两种格式说明符。
答案 1 :(得分:2)
这里的关键是:首先不要在printf
内进行任何形式的算术运算。与GUI分开的算法。
诸如printf("%d", p - q)
之类的代码非常危险,不仅因为您可能会在逻辑上弄错类型,而且因为C可能会“帮您一个忙”并通过隐式类型提升默默地更改类型。 Examples。
此外,大多数编译器不会警告错误的格式说明符。这是C历史上相对较新的事物,因为不需要编译器在此处显示诊断消息。这只是gcc的一个额外功能。
如何避免错误?这些功能本质上是危险的-事实就是如此,而且每个人都知道。就人类造成的总错误成本而言,可能的printf和scanf函数族是有史以来编程中最有害的函数。所以你应该怎么做:
stdio.h
,并使其远离生产质量代码。可移植性并不总是比健壮的代码更重要-有时最好使用原始控制台API。一般情况下,避免使用变量参数列表功能。stdio.h
的“ GUI”部分包装在单独的文件中,无论如何您都应该这样做。不要将打印/输入与算法混合使用。制作一个使用指针的接口。