为什么GCC会给我-Wjump-misses-init警告?

时间:2014-01-08 14:12:32

标签: c compiler-warnings

我有一段代码,当我以这种形式(带有-Wjump-misses-init标志)编写它时编译得很好:

int some_function(void) {

        ...

        if (is_error)
                goto error;

        int a;

        a = 1;

        return a;

error:
        return 666;
}

但是当我以这种形式编写相同的函数时,我在编译时会收到以下警告(:

int some_function(void) {

        ...

        if (is_error)
                goto error;

        int a = 1;

        return a;

error:
        return 666;
}

test.c: In function 'some_function':
test.c:15:17: warning: jump skips variable initialization [-Wjump-misses-init]
test.c:21:1: note: label 'error' defined here
test.c:17:13: note: 'a' declared here

为什么GCC在同一行上声明并初始化a时会给出警告?对我来说似乎有点奇怪?这些例子是荒谬的,但我担心我不能自由地泄露真正的代码片段。我在Debian Wheezy 7.3上运行GCC 4.7.2。

编辑:虚假错误

2 个答案:

答案 0 :(得分:3)

C ++ 中,您不允许bypasses declarations with initialization,但 C99 似乎允许这样做。如果您使用gcc-Wjump-misses-init,则可以-Wc++-compat向您发出警告。 gcc文档部分 Options to Request or Suppress Warnings中介绍了这一点,并说:

  

如果goto语句或switch语句在变量初始化时向前跳转,或者在变量初始化后向后跳转到标签,则发出警告。这仅警告声明它们时初始化的变量。此警告仅支持C和Objective-C;在C ++中,这种分支在任何情况下都是错误的。

     

-Wjump-misses-init包含在-Wc ++ - compat中。可以使用-Wno-jump-missses-init选项禁用它。

注意,这也适用于 switch 语句中的声明。解决此问题的一种方法是使用{}创建新范围。

附件I 中,draft C99 standard表示这是警告,它说:

  

实现可能会在许多情况下生成警告,其中没有一个是警告   作为本国际标准的一部分。以下是其中一些   常见情况。

并包含以下项目符号:

  

跳过具有自动存储持续时间的对象初始化的块   进入(6.2.4)。

答案 1 :(得分:1)

如果在跳转到a标签后使用error:变量,其值将是不确定的(6.2.4p6);这可能令人困惑,这就是为什么gcc警告它。 (在C ++中也是非法的。)

为了避免警告并仍然使用声明初始化,您可以将代码包装在一个块中:

int some_function(void) {
    {
        ...

        if (is_error)
                goto error;

        int a = 1;

        return a;
    }
error:
    return 666;
}

在这种情况下,您需要在块之外声明在error:标签之后使用的任何变量。