导致编译器发出虚假警告的场景是什么?

时间:2011-07-04 06:31:15

标签: c++ c compiler-construction

我有时会在源代码中阅读以前的开发人员的评论:

// and this is to make compiler stop crying

我认为使用C / C ++,你做的事情几乎是合法的,但编译器仍认为它是非法的。

是否有导致编译器发出虚假警告的方案列表?

3 个答案:

答案 0 :(得分:2)

我脑海中最明显的例子是gcc警告:

while (i = somefunc())

你用特定的复活节彩蛋压制警告:

while ((i = somefunc()))

当然假设警告不正确,并且您不打算写:

while (i == somefunc())

但它高度依赖于您的编码风格,您将在无错代码中触发警告。有些人,不可否认只是C程序员中的一小部分,一开始就不会在有条件的情况下进行任务,所以对他们来说这个警告不是“虚假”,因为如果他们得到它那么它总是 因为==的拼写错误。

答案 1 :(得分:2)

程序员可能会编写这样的注释的情况之一是编译器已经识别出的问题实际上是不可能的,但是超出了编译器确定该事实的能力。一个例子:

int foo(char *barArg) {
    char *barPtr, *grillPtr;
    if (barArg == NULL) {
        grillPtr = malloc(...);      /* allocate */
        get_default_bar(grillPtr);   /* initialize */
        barPtr = grillPtr;
    } else {
        barPtr = barArg;
    }

    /* Some common block of processing that does _not_ refer to grillPtr,
     * does _not_ assign to barArg, and _updates_ barPtr. */

    if (barArg == NULL) {
        free(grillPtr);              /* <<<----- here */
    }
    return 0;
}

在这种情况下,编译器完全有可能针对具有grillPtr的行发出关于潜在未初始化变量(free())的警告,因为它无法确定它是否可以只有在分配/初始化发生时才到达。

虽然更聪明的编译器可以更完整地理解流程图并确定代码实际上是安全的,但程序员更有可能通过在顶部设置grillPtrNULL来关闭代码功能,所以做一点额外的工作,以实现无警告的构建。 (还有其他方法可以达到相同的效果,但在声明变量时更容易理解正确。)

实际上,可以说这表明应该重新进行一些重构,以便将函数核心与所有的hokey设置/清理代码分开(并从两个分支调用,一个分配,另一个分配)缺少变量)。唉,在实践中安排并不总是那么容易。

答案 2 :(得分:1)

没有明确的此类警告列表,因为C标准不允许符合标准的编译器为合法代码发出警告或诊断消息。因此,每个C编译器都有自己的警告列表,其中一些可以触发完全正确,完全合法的代码(这个规范的例子是一个带有从未使用的参数的函数)。

这意味着代码更改以禁止此类警告通常针对特定的编译器(甚至可能是该编译器的特定版本) - 并且通常通过反复试验而不是事先预测发现。

然而,有时,这样的代码修改实际上使代码正确 - 被抑制的编译器诊断是C标准所要求的。通常的例子是赋值中需要的强制转换 - 例如,不能将整数值赋给指针对象,但大多数编译器都会发出警告并编译代码。在这种情况下添加一个强制转换会使警告静音,因为它会纠正代码 - 警告根本不是虚假的。