Ben*_*min 6 c c++ switch-statement duffs-device
我理解为什么Duff的设备比普通的循环代码更快,可以展开但没有优化.但我无法理解代码是如何编译的.
我想这是关于切换语法的一个技巧.但不是了.
怎样才能做到,而句子中存在开关句子?很奇怪.
有没有人可以解释这个?
编辑: 另一个问题.为什么duff使用8?它可能是16,65536或其他什么.因为代码大小?还有其他原因吗?例如,缓存或流水线操作的好处.
Ste*_*314 11
"它的工作原理"很简单.
C和C++都是编译语言,通常编译为平台机器代码.机器代码没有块结构的概念 - 所有块结构必须转换为使用(实际上)某些无条件和条件gotos混合的形式.
C语法规则允许switch语句和循环以不是真正的分层块结构的方式组合,但是纠缠控制流.只要编译器可以处理这个(任何好的编译器都应该),底层机器代码就没有问题.结果将是"spaghetti",但生成的机器代码通过优化器总是意大利面 - 它不是人类可读的,所以它不是问题.这里的问题是源代码也是spaghetti,即使gotos已被"隐藏".
注意 - 尽管任何好的编译器都应该处理Duffs设备,正如其他人已经评论过的那样,但这并不意味着它能够很好地应对以正确地优化它 - 只能很好地生成正确的可执行代码.这是曾经有目的的一些古老奇怪的习语,但现在更有可能混淆你的编译器并破坏它生成有效代码的能力.
编辑
以下是与Duffs设备有关,可能有助于说明基本思路......
switch (count & 1)
{
case 0 : goto lbl0;
case 1 : goto lbl1;
}
lbl0:
while (count != 0)
{
handle_one ();
count--;
lbl1:
handle_one ();
count--;
}
Run Code Online (Sandbox Code Playgroud)
在循环中包含case子句在概念上与在循环中具有goto-target标签没有什么不同,如上所述.
警告 - 这纯粹是为了说明一个想法,不应该复制到现实代码中.
Duff的Device编译原因的简单解释是switch语句的语法对switch语句块可能需要采用的形式并不特别具体.有一些限制,受控语句中允许的一些限制是在switch(case和default标签)之外不允许的.但除此之外,受控声明只是任何其他声明,可能存在switch目标标签.
这是C99的语法:
switch ( expression ) statement
Run Code Online (Sandbox Code Playgroud)
除了语法之外,标准还强加了一些约束:
case label表达式必须是整型常量表达式case标签表达或default标签除此之外,语句块中允许的任何构造都应该被允许在受控语句中(添加case和default标签都可以).请记住,case并且default只是标签交换机跳到基于控制表达式和case标签表达式. 正如Potatoswatter所说,switch只是一个计算goto.所以就像goto跳进循环的中间一样,也可以switch.
此外,我认为你可能会看到Duff设备的好处的情况今天非常罕见(我认为它们甚至在1980年代也很少见).不要忘记Tom Duff自己在他的描述中说了以下内容:
甚至比最初描述时更多,Duff的设备应该被认为是一种好奇而不是使用的工具.