【问题标题】:best way to get something like GCC -Wconversion but more usable?获得类似 GCC -Wconversion 但更有用的最佳方法?
【发布时间】:2021-12-11 08:34:33
【问题描述】:

如果没有 -Wconversion,编译器不会对此发出警告:

#include <inttypes.h>
#include <stdio.h>

static void foofunc (uint8_t arg) { printf ("arg: %i\n", arg); }
uint32_t biggie = 42000;
int main (void) { foofunc (biggie); return 0; }

即使使用 -Wall 和 -Wextra,编译器也会默默构建打印 16 的程序,我们都知道这是错误的 :)

但是使用 -Wconversion 你必须这样写:

#include <inttypes.h>
#include <stdio.h>

static void foofunc (uint8_t arg) { printf ("arg: %i\n", arg); }
uint8_t littlevar = 42; ;
int main (void) { foofunc ((uint8_t) (littlevar + 1)); return 0; }

我猜这是最后一次发生,因为加法运算在加法之前不知何故变成了 int。无论如何,使用 UINT8_C(1) 并不能解决它。然后有很多字符串等的演员表。

是否有一些我错过的中间方法可以捕捉 uint32_t 到 uint8_t 的完全钝化传递,同时又不需要在其他地方进行太多嘈杂的转换?

【问题讨论】:

  • 如果littlevar 的值为 255 会怎样?你想不想被警告?
  • @FredLarson 编译器不会警告运行时:)
  • @0___________:哦,我知道了。
  • @FredLarson 应该有警告**Warning** Style. Properly format your code
  • 也许我遗漏了一些东西,但在第二个示例中,演员阵容对我来说似乎是不必要的。 foofunc(littlevar + 1) 在没有警告的情况下工作得很好。例如:gcc.godbolt.org/z/5YGsM3Txn

标签: c gcc


【解决方案1】:

首先,static void foofunc (uint8_t arg) { printf ("arg: %i\n", arg); } 严格来说是错误的。你应该使用PRIu8 而不是%i

编译器默默地构建打印 16 的程序,我们都知道这是错误的

不,编译器和其他程序员都不知道这是错误的。将一个大整数截断为一个小整数可能是一个有效的用例,但最好是通过强制转换或分配给临时变量来进行显式转换。

但是使用 -Wconversion 你必须写这样的东西

最明显的代码更正是foofunc ((uint8_t)biggie),这与编译器无关。然而,在较新的 gcc 版本上,它确实使 -Wconversion 静音。

我猜这是最后一次发生,因为加法之前加法被转换成 int

是的,通过“通常的算术转换”,您可以获得隐式 int 转换,这正是您想要警告的那种微妙的 C 语言缺陷。而不是 unsigned 8 你会得到一个大的有符号类型。


总的来说,-Wconversion 不是很好,它带有很多误报。这不是您通常应该使用的选项,而是您应该在代码审查等期间临时激活的选项。

这类问题通常是通过外部静态分析工具而不是编译器发现的。一个例子是 clang-tidy,但也有很多商业的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2018-10-09
    • 2010-11-25
    相关资源
    最近更新 更多