在哪里放置switch / case语句与块

时间:2009-07-23 11:10:15

标签: c++ syntax

当我在C ++中的case代码块周围使用大括号来本地化变量时,我应该将break放在块的内部还是外部?

case FOO:  // 'break' inside
  {
    int i;
    doStuff();
    break;
  }

case BAR: // 'break' outside
  {
    int i;
    doStuff();
  }
  break;

感谢。

15 个答案:

答案 0 :(得分:21)

这是一种风格问题。

我会将break放在右大括号之外,以使其更具可读性。

答案 1 :(得分:15)

你把它放在任何你喜欢的地方。确保在整个项目中保持一致。 (就个人而言,我把它放在外面。)

答案 2 :(得分:5)

它应该出现在。

之后

例如:

switch(value)
{
   case 0:
   {
   // this ...
   // that ...
   // and the other ...
   }
   break;
}

以下编辑文字

这主要是为了提高可读性和可维护性,这是一个例子。

switch (value)
{
   case 0:
    // Do this...
    // Do that...
    break;
   case 1:
    //and the other...
   break;
}

switch (value)
{
   case 0:
    // Do this...
    // Do that...
    if (ObjectWithinScope.Type == Fault)
    break;
   case 1:
    //and the other...
   break;
}

现在与

进行比较
switch (value)
{
   case 0:
   {
    // Do this...
    // Do that...
   }
   break;
   case 1:
    //and the other...
   break;
}

   switch (value)
    {
       case 0:
       {
        // Do this...
        // Do that...
        if (ObjectWithinScope.Type == Fault)
        break;
       }
       case 1:
       {
        //and the other...           
       }
       break;
    }

当你开始遇到嵌套switch语句的情况时,它确实会变得非常混乱。

只是指针。

现在你们中的一些人仍然想知道我得到了什么。这里是。一段遗留代码停止工作,没有人能解决原因。这一切都归结为一段代码如下:

   switch (value)
    {
       case 0:
       {
        // Do this...
        // Do that...
        if (ObjectWithinScope.Type == Fault)
        break;
       }
       case 1:
       {
        //and the other...           
       }
       break;
    }

花了很长时间来确定这段代码,但是在检查更改日志时,它最初是跟随的:

   switch (value)
    {
       case 0:
       {
        // Do this...
        // Do that...
        if (ObjectWithinScope.Type == Fault)
            // *** A line of code was here ***
        break;
       }
       case 1:
       {
        //and the other...           
       }
       break;
    }

不可否认,原始代码本身并不一致,但是通过在大括号内中断代码,当一行代码被意外删除时编译的代码。如果中断位于括号之外,那么就不会有。

答案 3 :(得分:4)

我通常将break放在大括号内,如下所示:

switch (foo) {
    case bar: {
        int x = 5;
        printf("%d\n", x);
        break;
    }
    case baz: {
        // ...
        break;
    }
}

但是,因为这是我的规则,所以我可以随时打破它(没有双关语)。

答案 4 :(得分:4)

每个人都同意我们希望在switch/case...机制和每种情况下执行的实际行动之间有明显的区别。

因此,除非在每种情况下都有 nothing (简单分配等),我建议使用switch作为调度员,并委托'真实'帮助函数的东西。这自动解决了案例局部变量的问题,并完全抛弃了对括号的需求。

switch( operation ) {
  case cnegation: r = -value; break;
  case cinversion: r = 1./r; break;
  case cfaculty: { 
    double r = value; 
    while( value != 1 ) 
      r *= --value; 
  }
  break;
}

应该成为

switch( operation ) {
  case cnegation : r = negate (value) ; break;
  case cinversion: r = invert (value) ; break;
  case cfaculty  : r = faculty(value) ; break;
}

答案 5 :(得分:2)

这实际上取决于你的代码的逻辑以及它如何使用大括号,但为了得到正确的答案,如果你把它放在里面,试着把它们都放在里面。

答案 6 :(得分:1)

我认为你应该避免在switch语句中使用局部变量和块。此外,您应该避免使用长或复杂甚至级联的switch语句。 但没有规则没有例外......我更喜欢在块之后编写break语句。

答案 7 :(得分:1)

只要您和您的团队始终如一地做同样的事情,这并不重要。即便如此,如果不同的团队成员采用不同的方式,这也不是一个大问题。

我个人更喜欢之后。原因在于它在switch语句的机制(跳转,执行和退出)之间进行了一些分离,并且括号内的代码纯粹与案例的“做”有关。

例如:

switch( value )
{
    case 0:
        {
            // code here
        }
        break;

    default:
        {
            assert(!"unhandled value in switch");
        }
        break;
}

如果案例需要局部变量,我只使用{},但如果我在任何情况下使用{},我会将它们放在所有情况下。

我通常总是定义一个默认情况,断言是否有任何意外值。令人惊讶的是,其中一个断言经常会引发你的注意事项。

答案 8 :(得分:1)

我不喜欢在switch语句中添加任何类型的括号。就个人而言,如果这是一个复杂的操作,我喜欢把它放在一个函数中。没有什么比看到一个开关语句更令人烦恼的地方,每个“案例”之间有数百行代码,最重要的是它们中的一些在不同情况下重复,这使得无法进行维护。

例如:

switch(blah)
{
 case 1:
  // do one thing
  break;

 case 2:
  doManyThings();
  break;

 default:  
  // something
  break;
}

答案 9 :(得分:1)

这是一个古老的问题,但是我认为可以在此处添加一些重要的内容:样式不仅对美学很重要,而且在帮助防止由真实,易犯错误的人编写的真实软件方面可能会有所作为

尽管放在break语句的位置肯定是样式问题,而不是语言要求,但这里没有提到一种约定,如果遵循,则使阅读,编写更加容易,并查看switch语句,同时确保绝对不会出现意外情况。

样式如下:

switch(variable) {
    break; case 1 : statement;
    break; case 2 : {
       code in a block;
    }
    break; case 3 : other statement;
    /****/ case 4 : fall-through here on purpose.
    break; default: default behavior;
}

尽管您可能会说这只是样式上的一个小变化,但根据我的经验 (在关键的嵌入式系统代码中使用这种样式已有20多年的历史),它更容易编写,查看和维护这种代码。最大的原因是因为它改变了概念上的思维模式。

与其思考:“在这种情况下,要做一堆我必须认真考虑的事情... 哦,是的,然后突破或失败”,它迫使思考过程成为:“这要么是全新的情况,要么是前一案例的失败;现在,在这种情况下,做一堆我可以思考的事情,然后继续前进。”

答案 10 :(得分:0)

这是风格的问题,但是我把它理解为:

switch (variable)
{
    case expression:
        statement;
        break;
    default:
        statement;
        break;
}

其中statement是单个命令或块。中断与此语句或块分开。是的,我确实在默认情况下添加了一个休息时间,尽管它是多余的。我也 总是 在声明中加上括号。太多次我添加了一个声明只是为了打破范围。我将break更改为默认值,因为我更改了默认值:case case:并在其后添加了一些内容。防御性编码是你的朋友。

但是,我只能通过Microsoft找到实际定义的文档:

selection-statement:
    switch ( expression ) statement

labeled-statement:
    case constant-expression : statement
    default : statement

这表明它应该在里面。

然而,我认为从读者的角度来看,外界更清楚,但这肯定是主观的。

答案 11 :(得分:0)

由于标准不限制您选择break语句的位置,您可以选择任何您喜欢的内容。就个人而言,我使用以下风格:

 switch ( some_var ) {
        case 1: {
            // lot of code here
        } break;
        case 2: /* one call */ break;
        case 3: /* one call */ break;
        case 4: {
            // lot of code here again
        } break;
    }

答案 12 :(得分:0)

对于每个案例只使用一个语句而从不使用大括号的风格,有很多话要说。例如:

switch( cond ) {
default: foo(); break;
case 0: bar(); break;
case 1: baz(); break;
}

使用这种风格,你的问题没有实际意义。

答案 13 :(得分:0)

真实答案:编译器不关心。这是一个偏好的问题。

我把它们放在里面,就像google style guide一样。

如果使用大括号,我喜欢开口大括号与右大括号(与谷歌不同)在同一列上。

switch (var) {
  case 0: 
  {  
    ...      
    break;
  }
  case 1: 
  {
    ...
    break;
  }
  default: 
    assert(false);
}

答案 14 :(得分:0)

我的观点...请参阅下面的示例。

缩进开关的所有情况,并在关键字switch下使用开关的右括号,就像在if语句中一样。每当需要时,每个case语句使用相同的规则:在case语句后面的半列后打开括号,并在关键字case下关闭它们,然后缩进每个case的内容{1}}语句包括关键字break

保持一致(缩进和括号位置)和简短(每个case语句不超过5-10行代码。复杂项目失败,因为代码太多的错误缩进switch语句在他们中间。

    switch (number) {

        case 1:
            logFileStderr(VERBOSE, "MESSAGE: switch without brackets...\n");
            break;

        case 2: {
            logFileStderr(VERBOSE, "MESSAGE: switch with brackets...\n");
            break;
        }

        default:
            logFileStderr(VERBOSE, "WARNING: Unknown option...\n");
            break;
    }