为了账号安全,请及时绑定邮箱和手机立即绑定

为什么不能在开关语句中声明变量?

为什么不能在开关语句中声明变量?

C++ C
慕斯709654 2019-05-31 17:09:15
为什么不能在开关语句中声明变量?我一直在想,为什么不能在开关语句中的CASE标签之后声明变量呢?在C+中,您可以在任何地方声明变量(并且声明它们接近第一次使用显然是件好事),但是下面的内容仍然不能工作:switch (val)  {  case VAL:     // This won't work   int newVal = 42;     break;case ANOTHER_VAL:     ...   break;}以上给出了以下错误(MSC):“newVal”的初始化由“case”标签跳过在其他语言中,这似乎也是一个限制。为何会出现这样的问题呢?
查看完整描述

3 回答

?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

Case陈述仅限于标签..这意味着编译器将解释为直接跳转到标签。在C+中,这里的问题是范围问题之一。您的花括号将作用域定义为switch声明。这意味着您将有一个范围,在该范围内,将在代码中执行跳转,跳过初始化。正确的处理方法是定义一个特定于case语句,并在其中定义变量。

switch (val){   case VAL:  {
  // This will work
  int newVal = 42;  
  break;}case ANOTHER_VAL:  ...break;}


查看完整回答
反对 回复 2019-05-31
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

这个问题最初被标记为[C]和[C+]。原来的代码在C和C+中都是无效的,但是由于完全不同的原因。我相信这个重要的细节被现有的答案所遗漏(或混淆)。

  • 在C+中,此代码无效,因为case ANOTHER_VAL:标签跳入变量的范围。newVal绕过它的初始化。跳过本地对象的初始化在C+中是非法的。大多数答案都正确地处理了这个问题的这一面。

  • 但是,在C语言中,绕过变量初始化并不是一个错误。在初始化时跳入变量的范围在C中是合法的。它只是意味着变量没有初始化。由于完全不同的原因,原始代码没有在C中编译。标签case VAL:在原始代码中,变量的声明附加在一起。newVal..在C语言中,声明不是语句。他们不能被贴上标签。当这段代码被解释为C代码时,这就是导致错误的原因。

    switch (val)  {  case VAL:             /* <- C error is here */
      int newVal = 42;  
      break;case ANOTHER_VAL:     /* <- C++ error is here */
      ...
      break;}

加一个额外的{}块修复了C+和C两个问题,尽管这些问题恰好不同。在C+方面,它限制了newVal,确保case ANOTHER_VAL:不再跳入该范围,从而消除了C+问题。在C边那额外的{}引入复合语句,从而使case VAL:标签可应用于语句,从而消除了C问题。

  • 在C情况下,这个问题可以很容易地解决,而不需要{}..之后添加一个空语句即可。case VAL:标签和代码将变得有效。

    switch (val)  {  case VAL:;            /* Now it works in C! */
      int newVal = 42;  
      break;case ANOTHER_VAL:  
      ...
      break;}

    注意,尽管从C的角度来看,它现在是有效的,但从C+的角度来看,它仍然是无效的。

  • 对称地说,在C+情况下,这个问题可以很容易地解决,而不需要{}..只要从变量声明中删除初始化程序,代码就会生效。

    switch (val)  {  case VAL: 
      int newVal;
      newVal = 42;  
      break;case ANOTHER_VAL:     /* Now it works in C++! */
      ...
      break;}

    注意,尽管从C+的角度来看,它现在是有效的,但从C的角度来看,它仍然是无效的。


查看完整回答
反对 回复 2019-05-31
?
Qyouu

TA贡献1786条经验 获得超11个赞

好的。严格地澄清这一点与声明无关。它只涉及“跳过初始化”(ISO C+‘03 6.7/3)

这里的许多帖子提到,跳过声明可能会导致变量“未声明”。这不是真的。POD对象可以在没有初始化器的情况下被声明,但是它有一个不确定的值。例如:

switch (i){
   case 0:
     int j; // 'j' has indeterminate value
     j = 0; // 'j' initialized to 0, but this statement
            // is jumped when 'i == 1'
     break;
   case 1:
     ++j;   // 'j' is in scope here - but it has an indeterminate value
     break;}

如果对象是非POD或聚合,编译器将隐式添加初始化器,因此不可能跳过这样的声明:

class A {public:
  A ();};switch (i)  // Error - jumping over initialization of 'A'{
   case 0:
     A j;   // Compiler implicitly calls default constructor
     break;
   case 1:
     break;}

此限制不限于开关语句。使用“goto”跳过初始化也是一个错误:

goto LABEL;    // Error jumping over initializationint j = 0; LABEL:
  ;

有一点需要注意的是,这是C+和C之间的区别,在C中,跳过初始化并不是一个错误。

正如其他人所提到的,解决方案是添加一个嵌套块,以便变量的生存期仅限于个别的CASE标签。


查看完整回答
反对 回复 2019-05-31
  • 3 回答
  • 0 关注
  • 787 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信