代码之家  ›  专栏  ›  技术社区  ›  gsamaras a Data Head

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

  •  6
  • gsamaras a Data Head  · 技术社区  · 6 年前

    当我执行这段代码时 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公司 是的。

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

    2 回复  |  直到 6 年前
        1
  •  2
  •   gsamaras a Data Head    6 年前

    我想你看不出来。这取决于编译器编写器的意图/警告/智能。

    也许他决定永远支持 %ld 哪里 %td 是预期的,或者他只是不知道/无法/不愿意给出更详细/正确的信息。如果有疑问,你的最后手段是标准。

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

        2
  •  2
  •   Lundin    6 年前

    这里的关键是:不要在里面做任何形式的算术 printf 首先。将算法与gui分离。

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

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

    如何避免虫子?这些功能本质上是危险的——这就是它的本质,每个人都知道。可能printf&scanf函数家族是编程史上最有害的函数,就对人类造成的总错误代价而言。所以你应该怎么做:

    • 避免 stdio.h 如果可能的话,把它和生产质量代码分开。可移植性并不总是比健壮的代码更重要——有时最好使用原始控制台api。一般避免使用变量参数列表函数。
    • 如果无法避免,请将 标准 在一个单独的文件中,无论如何你都应该这样做。不要将打印/输入与算法混用。创建一个使用指针的接口。
    • 现在是2018年,不是1970年:首先不要编写控制台接口。是的,我知道…有很多旧垃圾仍在漂浮,需要维护。但是现在,控制台功能应该主要用于调试和学习c语言的新手,在这种情况下类型安全可能不是一个大问题。