考虑下面的switch语句:

switch( value )
{
  case 1:
    return 1;
  default:
    value++;
    // fall-through
  case 2:
    return value * 2;
}

此代码编译,但它是有效的(=定义的行为)C90/C99?我从未见过默认情况不是最后一个情况的代码。

编辑: 正如Jon Cage和KillianDS所写的:这真的是丑陋而令人困惑的代码,我很清楚这一点。我只对通用语法(有定义吗?)和预期的输出感兴趣。


当前回答

我有一个有趣的例子,把默认值放在顶部保存的程序空间。它是为Arduino Nano设计的,节省了8字节的闪存(RAM是一样的)。 供你参考,这两组代码是

#if 1 // toggle this 0 or 1
// 3138/265 bytes
uint8_t g_BuiltinLedGlowState = 0; // dropping '= 0' saves nothing
void AdvanceBuiltinLedGlow_3Ph(){
  switch(++g_BuiltinLedGlowState){
  default: 
    g_BuiltinLedGlowState = 0;
    // drop through // break;
  case 0: // bright
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    break;
  case 1: // dim
    pinMode(LED_BUILTIN, INPUT_PULLUP);
    break;
  case 2: // off
    pinMode(LED_BUILTIN, INPUT);
    break;
  }
}
#elif 1
// 3146/265 bytes
uint8_t g_BuiltinLedGlowState = 0; // dropping '= 0' saves nothing
void AdvanceBuiltinLedGlow_3Ph(){
  switch(++g_BuiltinLedGlowState){
  case 1: // bright
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    break;
  case 2: // dim
    pinMode(LED_BUILTIN, INPUT_PULLUP);
    break;
  case 3: // off
    pinMode(LED_BUILTIN, INPUT);
    // drop through // break;
  default: 
    g_BuiltinLedGlowState = 0;
    break;
  }
}
#endif

// the loop function runs over and over again forever
void loop() {
  Serial.println(g_BuiltinLedGlowState, DEC);
  AdvanceBuiltinLedGlow_3Ph();
  delay(1000);
}

其他回答

另一个例子:如果“default”是一个意外的情况,并且您希望记录错误,但也要做一些合理的事情,那么这可能很有用。示例来自我自己的一些代码:

  switch (style)
  {
  default:
    MSPUB_DEBUG_MSG(("Couldn't match dash style, using solid line.\n"));
  case SOLID:
    return Dash(0, RECT_DOT);
  case DASH_SYS:
  {
    Dash ret(shapeLineWidth, dotStyle);
    ret.m_dots.push_back(Dot(1, 3 * shapeLineWidth));
    return ret;
  }
  // more cases follow
  }

我不知道你是否可以称它为“丑”,当然,在你必须写的情况下,它非常有用:

    switch (cond) {
       case default: Instruction1;
               ...
               InstructionN;
       case 1: FinalInstruction;
    }

您可以避免编写两次代码

switch语句中没有定义的顺序。你可以把这些情况看作一个命名标签,一个goto标签。与人们在这里的想法相反,在值2的情况下,默认标签不会跳转到。为了用一个经典的例子来说明,这里是Duff的设备,它是C语言中switch/case的极端代表。

send(to, from, count)
register short *to, *from;
register count;
{
  register n=(count+7)/8;
  switch(count%8){
    case 0: do{ *to = *from++;
    case 7:     *to = *from++;
    case 6:     *to = *from++;
    case 5:     *to = *from++;
    case 4:     *to = *from++;
    case 3:     *to = *from++;
    case 2:     *to = *from++;
    case 1:     *to = *from++;
            }while(--n>0);
  }
}

我有一个有趣的例子,把默认值放在顶部保存的程序空间。它是为Arduino Nano设计的,节省了8字节的闪存(RAM是一样的)。 供你参考,这两组代码是

#if 1 // toggle this 0 or 1
// 3138/265 bytes
uint8_t g_BuiltinLedGlowState = 0; // dropping '= 0' saves nothing
void AdvanceBuiltinLedGlow_3Ph(){
  switch(++g_BuiltinLedGlowState){
  default: 
    g_BuiltinLedGlowState = 0;
    // drop through // break;
  case 0: // bright
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    break;
  case 1: // dim
    pinMode(LED_BUILTIN, INPUT_PULLUP);
    break;
  case 2: // off
    pinMode(LED_BUILTIN, INPUT);
    break;
  }
}
#elif 1
// 3146/265 bytes
uint8_t g_BuiltinLedGlowState = 0; // dropping '= 0' saves nothing
void AdvanceBuiltinLedGlow_3Ph(){
  switch(++g_BuiltinLedGlowState){
  case 1: // bright
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    break;
  case 2: // dim
    pinMode(LED_BUILTIN, INPUT_PULLUP);
    break;
  case 3: // off
    pinMode(LED_BUILTIN, INPUT);
    // drop through // break;
  default: 
    g_BuiltinLedGlowState = 0;
    break;
  }
}
#endif

// the loop function runs over and over again forever
void loop() {
  Serial.println(g_BuiltinLedGlowState, DEC);
  AdvanceBuiltinLedGlow_3Ph();
  delay(1000);
}

是的,这是有效的,在某些情况下甚至是有用的。一般来说,如果你不需要它,就不要做。