【发布时间】:2021-11-16 23:32:42
【问题描述】:
对于我所知道的所有 C 编译器,-Wall 会警告隐式转换,但不会警告任何显式转换。我一直在尝试找到一个标志(无论它是否用于 gcc、clang,任何 c 编译器都会这样做),当存在导致未定义或实现定义的行为的强制转换时,它将导致发出警告。下面是一个示例,说明了我会在哪里和不会出现警告:
#include <math.h>
struct person {
int tag;
char* name;
};
int foo(struct person* p) {
int* tagPtr = (int*)p; // this cast is fine, cast to first member ptr is allowed
double* badPtr = (double*)p; // this cast should cause warning
return ((*tagPtr) + (int)(round(*badPtr)));
}
int* 的强制转换是明确定义的,double* 的强制转换不是,但是 gcc 没有警告我关于第二次强制转换。有没有办法让它这样做?或者其他编译器甚至 linter 是否提供此功能?
然后是“明确定义”和“明确实现定义”之间的区域,即“可以根据上下文明确定义”。例如,如果 int* 最初是由另一个方向的转换形成的(由 C 规范的第 6.7.2.1p15 节暗示),则从 int* 转换为 struct person* 是明确定义的。指针的出处很少可用,因此编译器或 linter 不会知道此转换是否正确,只知道它可能是正确的。为了对我有用,warn-on-dangerous-cast 功能需要在这种情况下不警告,仅在保证强制转换为实现定义行为的情况下。
有没有工具可以帮助解决这个问题?
对于上下文,我正在使用 C 作为带有标记变体的语言的目标。如果变体具有不同的尺寸,则铸造是必不可少的。但是,如果编译器可以通过确保我不进行任何无意义的强制转换来帮助检查我生成的代码,那就太好了。我怀疑优化编译器应该具有提供此警告的信息,因为这与别名分析所需的信息相同。我只是无法弄清楚是否有任何编译器为此目的而弯曲信息。
【问题讨论】:
-
C 中类型转换的许多要点是告诉编译器,“我保证我知道我在做什么,所以不要抱怨。”所以我认为你不太可能找到一个编译选项告诉编译器,“继续,然后再猜我。”
-
这并非史无前例。像 gcc 的
-Wcast-align=strict这样的编译器选项指示编译器对用户进行第二次猜测,并对某些显式转换发出警告。 -
对于clang,答案是否定的。它有一个方便的
-Weverything选项,可以启用它实现的每个警告,这不会在您的代码上给出相关警告。 godbolt.org/z/91vEPKjz3
标签: c gcc clang compiler-warnings gcc-warning