可以管窥switch/case的Duff设施

C是这样一种语言, 在你知道它足够强大,足够古怪,觉得不会再有什么能让你感到吃惊的语法时,又会发掘出新的令人震惊的东西。

今天看到的所谓Duff设施便是这样一种东西。

我们知道,编译器有时为了效率,会将循环展开。偶尔,或许也存在需要手工展开循环进行优化的代码。展开循环时,循环体的内容被复制了k份,而原本需要迭代N次的循环则只迭代N/k次,余数部分则需要再循环一次。例如:

int i = 0, sum = 0; while( i < N ) { sum += i; i++; }

变换为:

int i = 0, j = N/4, sum = 0; while( j-- > 0 ) { sum += i; i++; sum += i; i++; sum += i; i++; sum += i; i++; } while( i < N ) { sum += i; i++; }

1983年,Tom Duff提出了“简化”这种C代码的一种方式,即所谓“Duff设施”用一个循环解决问题:

int i = 0, j = N/4, sum = 0; switch( N % 4 ) { case 0: while( j-- > 0 ) { sum += i; i++; case 3: sum += i; i++; case 2: sum += i; i++; case 1: sum += i; i++; } }

这样的代码或许并非是“好”的代码,却可以让我们一窥switch/case的究竟。

编译器并没有将每个case作为switch下的一支来处理,而是将所有的代码放入一个块中。这就是为什么每个case下面可以堆叠多条语句,且不同的case下面不能定义同样的变量的原因了。

事实上,case在switch语句中只起了一个标号的作用,上面的代码大致与以下代码相同:

int i = 0, j = N/4, sum = 0; if( N % 4 == 0 ) goto case0; else if( N % 4 == 1 ) goto case1; else if( N % 4 == 2 ) goto case2; else if( N % 4 == 3 ) goto case3; case0: while( j-- > 0 ) { sum += i; i++; case3: sum += i; i++; case2: sum += i; i++; case1: sum += i; i++; }

 

PS:文中所有代码均在 VS 2008 中测试通过

你可能感兴趣的:(c,优化,测试,语言,编译器)