case-switch的工作方式是这样的吗?

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

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

令我惊讶的是,在变量为c的情况下,路径进入了“此处代码”段。 我同意在案例开关的c部分结束时没有中断,但我会想象它会通过default 。 当你降落在一个case blah:行,是不是检查你当前的值是否与特定情况相符, 然后只让你进入特定的段? 否则案件的重点是什么?

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

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

 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 ,它会离开开关块。

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

举例:

 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; } 

这被称为堕落。

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

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

 // 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和默认是相似的,所有这些都落到默认逻辑(忽略)。

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

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

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

实际上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情况的代码是相同的,除了在字符串的情况下计算大小。