| 
				打卡等级:以坛为家III打卡总天数:653最近打卡:2025-10-30 11:54:16 金牌会员 
 
 
	积分1015 
 | 
 
 发表于 2025-6-6 11:14:57
|
显示全部楼层 
| 这段代码确实没问题,有点令人意外,case 是可以放在 switch 中的代码块里面的。
 
 Duff's device
 
 The famous "Duff's device" in C makes use of the fact that a `case` statement is still legal within a sub-block of its matching `switch` statement. Tom Duff used this for an optimised output loop:
 
 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 ((count -= 8) > 0);
 }
 ```
 
 We can put it to a slightly different use in the coroutine trick. Instead of using a `switch` statement to decide which `goto` statement to execute, we can use the `switch` statement to perform the jump itself:
 
 int function(void)
 {
 static int i, state = 0;
 switch (state)
 {
 case 0: /* start of function */
 for (i = 0; i < 10; i++)
 {
 state = 1; /* so we will come back to "case 1" */
 return i;
 case 1:; /* resume control straight after the return */
 }
 }
 }
 
 Now this is looking promising. All we have to do now is construct a few well chosen macros, and we can hide the gory details in something plausible-looking:
 
 ```
 #define crBegin static int state=0; switch(state) { case 0:
 #define crReturn(i,x) do { state=i; return x; case i:; } while (0)
 #define crFinish }
 int function(void)
 {
 static int i;
 crBegin;
 for (i = 0; i < 10; i++)  crReturn(1, i);
 crFinish;
 }
 ```
 
 (note the use of `do ... while(0)` to ensure that `crReturn` does not need braces around it when it comes directly between `if` and `else`)
 
 This is almost exactly what we wanted. We can use `crReturn` to return from the function in such a way that control at the next call resumes just after the return. Of course we must obey some ground rules (surround the function body with `crBegin` and `crFinish`; declare all local variables `static` if they need to be preserved across a `crReturn`; *never* put a `crReturn` within an explicit `switch` statement); but those do not limit us very much.
 
 The only snag remaining is the first parameter to `crReturn`. Just as when we invented a new label in the previous section we had to avoid it colliding with existing label names, now we must ensure all our state parameters to `crReturn` are different. The consequences will be fairly benign - the compiler will catch it and not let it do horrible things at run time - but we still need to avoid doing it.
 
 Even this can be solved. ANSI C provides the special macro name `__LINE__`, which expands to the current source line number. So we can rewrite `crReturn` as
 
 ```
 #define crReturn(x) do { state=__LINE__; return x; \
 case __LINE__:; } while (0)
 ```
 
 and then we no longer have to worry about those state parameters at all, provided we obey a fourth ground rule (never put two `crReturn` statements on the same line).
 | 
 |