case-switch是否像这样工作?

时间:2011-11-16 02:55:33

标签: c++ c

我今天遇到了一个代码转换代码,看到它是如何工作的,有点惊讶。代码是:

switch (blah)
{
case a:
  break;
case b:
  break;
case c:
case d:
case e: 
  {
    /* code here */
  }
  break;
default :
  return;
}

令我惊讶的是,在变量为c的情况下,路径进入了"代码在这里"分割。我同意在案例切换的c部分结尾处没有中断,但我想象它会通过default来代替。当您降落在case blah:行时,它是否会检查您当前的值是否与特定情况匹配,然后只有让您进入特定细分市场?否则,案件的重点是什么?

5 个答案:

答案 0 :(得分:15)

这称为案例落实,是一种理想的行为。它允许您在案例之间共享代码。

如何使用案例直通行为的示例:

switch(blah)
{
case a:
  function1();
case b:
  function2();
case c:
  function3();
  break;
default:
  break;
}

如果您在blah == a时输入切换,则会执行function1()function2()function3()

如果您不想有此行为,可以通过添加break语句来选择退出。

switch(blah)
{
case a:
  function1();
  break;
case b:
  function2();
  break;
case c:
  function3();
  break;
default:
  break;
}

switch语句的工作方式是(或多或少)执行goto跳转到case标签,并从那一点继续运行。当执行命中break时,它会离开开关块。

答案 1 :(得分:10)

这是正确的行为,它被称为“堕落”。这使您可以使用相同的代码处理多个案例。在高级情况下,您可能希望在一种情况下执行某些代码,然后再转到另一种情况。

受挫的例子:

switch(command)
{
   case CMD_SAVEAS:
   {
      this->PromptForFilename();
   } // DO NOT BREAK, we still want to save
   case CMD_SAVE:
   {
      this->Save();
   } break;


   case CMD_CLOSE:
   {
      this->Close();
   } break;

   default:
      break;
}

答案 2 :(得分:4)

这被称为堕落。

它正是你所看到的:几种情况将执行同一段代码。

对某些情况进行额外处理也很方便,还有一些共享逻辑:

// psuedo code:
void stopServer() {
    switch (serverStatus)
    case STARTING:
    {
        extraCleanUpForStartingServer();
        // fall-thru
    }
    case STARTED:
    {
        deallocateResources();
        serverStatus = STOPPED;
        break;
    }
    case STOPPING:
    case STOPPED:
    default:
        // ignored
        break;
}

这是切换机箱中的跌落的典型用法。在STARTING和STARTED的情况下,我们需要执行deallocateResources并将状态更改为STOPPED,但STARTING需要一些额外的清理。通过上述方式,您可以在STARTING中清楚地呈现“共同逻辑”和额外逻辑。

STOPPED,STOPPING和默认类似,所有这些都落到默认逻辑(忽略)。

这样编码并不总是一种好方法,但如果使用得当,它可以更好地呈现逻辑。

答案 3 :(得分:2)

幸运的是,C ++并不依赖于你的想象力: - )

将开关标签视为“goto”标签,switch(blah)只需“转到”相应的标签,然后代码就会从那里流出。

答案 4 :(得分:2)

实际上,switch语句的工作方式与您观察的方式相同。它的设计使您可以将多个案例组合在一起,直到遇到中断并且它就像筛子一样。

以下是我的一个项目的真实示例:

struct keystore_entry *new_keystore(p_rsd_t rsd, enum keystore_entry_type type, const void *value, size_t size) {
        struct keystore_entry *e;
        e = rsd_malloc(rsd, sizeof(struct keystore_entry));
        if ( !e ) 
                return NULL;
        e->type = type;
        switch (e->type) {
        case KE_DOUBLE:
                memcpy(&e->dblval, value, sizeof(double));
                break;
        case KE_INTEGER:
                memcpy(&e->intval, value, sizeof(int));
                break;

        /* NOTICE HERE */

        case KE_STRING:
                if ( size == 0 ) { 
                        /* calculate the size if it's zero */
                        size = strlen((const char *)value);
                }
        case KE_VOIDPTR:
                e->ptr = rsd_malloc(rsd, size);
                e->size = size;
                memcpy(e->ptr, value, size);
                break;

        /* TO HERE */
        default:
                return NULL;
        }
        return e;
}

除了字符串大小的计算外,KE_STRINGKE_VOIDPTR个案的代码是相同的。