我今天遇到了一个代码转换代码,看到它是如何工作的,有点惊讶。代码是:
switch (blah)
{
case a:
break;
case b:
break;
case c:
case d:
case e:
{
/* code here */
}
break;
default :
return;
}
令我惊讶的是,在变量为c
的情况下,路径进入了"代码在这里"分割。我同意在案例切换的c
部分结尾处没有中断,但我想象它会通过default
来代替。当您降落在case blah:
行时,它是否会检查您当前的值是否与特定情况匹配,然后只有让您进入特定细分市场?否则,案件的重点是什么?
答案 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_STRING
和KE_VOIDPTR
个案的代码是相同的。