具有相同名称的静态变量的开关案例的独立范围

时间:2014-02-26 12:28:04

标签: c++ c static scope switch-statement

更新: 我现在重新测试了简化的测试用例和恢复共享名称的完整代码,并且它可以正常工作。我的代码中的其他地方可能还有一些其他错误现在已修复。很抱歉浪费你的时间和精力;将来不会在没有工作测试用例的情况下发布。 Mea culpa。


我有一个C ++函数,我反复调用它。它有以下片段

     switch(c)
     {
     case 1:
        {
          static int i = 0;
          if ( ... )  { i = 0; }
          .... 
          break;
        }
     case 2:
        {
          static int i = 0;
          if ( ... )  { i = 0; }
          .... 
          break;
        }
     case 3:
        {
          static int i = 0;
          if ( ... )  { i = 0; }
          .... 
          break;
        }
     }

这个想法是它必须记住每个案例的状态,有时它必须重置它。

它无法正常工作。当我调试它时(MSVC ++ 2010 Express Edition),我注意到每个i都没有独立行为,它们的价值看起来似乎在变化;此外,当重置条件被点击时,相应的if输入OK,但i = 0;语句只是... 跳过 !!!并且“locals”窗口显示i及其先前的值,不变(当前语句是下一个,仍在if内)。 if内的其他陈述正在正确执行。

当我使用唯一名称(ii1i2)重命名每个i3时,问题就消失了。

这是一些我应该知道的错误或某些语言功能吗?我认为每个块{ ... }定义了独立范围。这里发生了什么?它会在C中工作吗?

编辑:抱歉没有构建测试用例。会这样做,稍后再报告。

4 个答案:

答案 0 :(得分:4)

这听起来像是代码或解释中的错误。我可以想象你的调试器中的“监视窗口”功能会出错,因为块没有名称,因此难以在文本中识别。

static存储持续时间的本地变量受块范围约束。

以下是具有功能范围的证据:

  

[C++11: 3.3.5/1]:标签(6.1)具有功能范围,可以在声明它们的函数中的任何位置使用。 只有标签才有功能范围。

这是一个实际的演示:

#include <iostream>

void f(const int i)
{
    switch (i) {
        case 3: {
            static int x = 0;
            std::cout << x;
            x = 3;
            std::cout << x << ' ';
            break;
        }

        case 4: {
            static int x = 0;
            std::cout << x;
            x = 4;
            std::cout << x << ' ';
            break;
        }
    }
}

int main()
{
    f(3);
    f(4);
}

// Output: 03 04

这表明当输入第二种情况时,您正在使用不同的本地静态变量x。否则你会看到03 34

Live demo using GCC 4.8;我在Visual Studio 2012中获得了相同的结果。

答案 1 :(得分:3)

函数内部的静态变量具有块作用域,并且它们在连续调用它时是持久的。您不能在同一范围内声明两个具有相同名称的变量,但如果它们位于不同的范围内,则可以这样做,表示为

{}

这是你的情况。

switch(c)
 {
 case 1:
    {
      static int i = 0;
    }
 case 2:
    {
      static int i = 0;
    }
 case 3:
    {
      static int i = 0; 
    }
 }

所以这应该按照你的预期工作,因此这可能是编译器,调试器(或者其他没有给出更多信息的情况下很难猜到的)的错误,它将所有这些静态变量视为同一个变量。这就是为什么更改这些变量的名称可以解决您的问题。

答案 2 :(得分:1)

我必须自己检查,以为我会分享我的小测试。变量仅在大括号内可见。并且可以在另一个案例中声明相同的变量名称,它不会覆盖另一个变量。

变量在函数中不可见,但仅在switch语句中的花括号内。

#include<stdio.h>
int call_switch(int);
int main()
{
call_switch(2);
call_switch(3);
call_switch(2);
call_switch(3);
return 0;
}

int call_switch(int a){
switch(a)
{ 
   case 2:
   {
     static int i = 5;
     i++;
     printf(" i declared as 5     %d\n",i);
     break;
   }
   case 3:
   {
     static int i = 10;
     i++;
     printf("i declared as 10   %d\n",i);
     break;
   }
}
  // printf("%d",i ); not visible here
  return 0;

}

输出

i declared as  5     6
i declared as 10    11
i declared as  5     7
i declared as 10    12

答案 3 :(得分:-1)

函数内的

static变量具有函数范围。变量在整个函数中都可见。

函数外部的

static个变量有文件范围,它在文件中可见,但不在文件中可见。