我有一段代码,当我以这种形式(带有-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。
编辑:虚假错误
答案 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:
标签之后使用的任何变量。