在玩代码时,我注意到一个奇怪的行为,我不知道解释背后的逻辑
void foo(int n)
{
int m = n;
while (--n > 0)
{
switch (n)
{
case -1:
case 0:
for (int j = 0; j < m; ++j)
default:
printf(":-)");
break;
}
}
}
int main()
{
foo(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望printf
执行比方说的10
时间。然后,我看到它继续运行(想象一下100000,而不是10),并假定开发(VS)解释了printf
内部的for
(漂亮的预期),因此输出由n
次,每次入口switch
。
但后来证明j
从未初始化。
所以我的问题是为什么?这是未定义的行为吗?这不是一个,据说,标准代码?
回顾一些第三方C代码我遇到了类似的事情:
switch (state) {
case 0:
if (c=='A') { // open brace
// code...
break; // brace not closed!
case 1:
// code...
break;
} // close brace!
case 2:
// code...
break;
}
Run Code Online (Sandbox Code Playgroud)
在我正在审查的代码中看起来只是一个错字,但我很惊讶它编译时没有错误.
为什么这个有效的C?
与在预期位置关闭支撑相比,对此代码执行的影响是什么?
有什么情况可以使用吗?
编辑:在示例中,我查看了存在的所有中断(如上所述) - 但如果在0或1的情况下中断,则答案还可以包括行为.
我们知道Duff的设备使用隔行开关和循环的结构交错,如:
send(to, from, count)
register short *to, *from;
register count;
{
register n = (count + 7) / 8;
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 (--n > 0);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在Swif 2.1中,当我们在Swift文档中读到时,switch-case控制流并没有隐含地落后:
没有隐含的堕落 …
使用库存Sun 1.6编译器和JRE/JIT,使用Duff的设备示例的大量展开来展开循环是一个好主意吗?或者它最终是代码混淆,没有性能优势?
我使用的Java分析工具对于逐行CPU使用的信息比valgrind少,所以我希望通过其他人的经验来增加测量.
请注意,当然,你不能完全编写Duff的设备,但你可以做基本的展开,这就是我想知道的.
short stateType = data.getShort(ptr);
switch (stateType) {
case SEARCH_TYPE_DISPATCH + 16:
if (c > data.getChar(ptr + (3 << 16) - 4)) {
ptr += 3 << 16;
}
case SEARCH_TYPE_DISPATCH + 15:
if (c > data.getChar(ptr + (3 << 15) - 4)) {
ptr += 3 << 15;
}
...
Run Code Online (Sandbox Code Playgroud)
通过许多其他价值观.
就在昨晚,我第一次遇到了好奇的Duff设备.我一直在做一些阅读,我不认为这是令人生畏的理解.我很好奇的是奇怪的语法(来自维基百科):
register short *to, *from;
register int count;
{
register int n = (count + 7) / 8;
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(--n > 0);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在阅读switch语句的C++标准定义(如果过时,请告诉我,我不熟悉Open-Std.org).据我所知,case语句只是简化的switch语句,供switch语句使用.
开关本身完全忽略嵌套的do-while,循环忽略case语句.由于开关在循环内部跳转,因此执行循环.开关用于覆盖剩余部分(从8除以),循环处理可被整除的部分.这一切都有道理.
我的问题是为什么笨拙的语法?在我看来,可以编写循环使得所有case语句都包含在其中,是吗?我在标准中没有看到禁止此行为的任何内容,并且它在GCC 4.7下正确编译,以下被认为是合法的吗?
register short …
Run Code Online (Sandbox Code Playgroud) 我最近阅读了有关奇怪的C代码段的页面.大多数都是可以理解的.但我无法理解这一点:
switch(c & 3) while((c -= 4) >= 0){
foo(); case 3:
foo(); case 2:
foo(); case 1:
foo(); case 0:
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮我解释一下这段代码背后的逻辑是什么?它是如何工作的?
我理解为什么Duff的设备比普通的循环代码更快,可以展开但没有优化.但我无法理解代码是如何编译的.
我想这是关于切换语法的一个技巧.但不是了.
怎样才能做到,而句子中存在开关句子?很奇怪.
有没有人可以解释这个?
编辑: 另一个问题.为什么duff使用8?它可能是16,65536或其他什么.因为代码大小?还有其他原因吗?例如,缓存或流水线操作的好处.
我在这里有一个循环,我想让它运行得更快.我正在传递一个大阵列.我最近听说过Duff的设备可以应用于这个for循环吗?有任何想法吗?
for (i = 0; i < dim; i++) {
for (j = 0; j < dim; j++) {
dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}
}
Run Code Online (Sandbox Code Playgroud) 我已经读过好几次了(例如,这里的编译器:如果条件始终为true / false怎么办),任何像样的c ++编译器都会选择退出
if(false)
{
...
}
Run Code Online (Sandbox Code Playgroud)
但是,如果有意跳入此if(false)
障碍该怎么办。我有这样的想法
#include <iostream>
void func(int part){
switch (part) {
case 0:{
if(false)
case 1:{std::cout << "hello" << std::endl;}
break;
}
default:
break;
}
}
int main()
{
func(0);
func(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是否有任何体面的C ++编译器会尊重这种跳跃,还是最终会在退出时出现一些问题?
duffs-device ×10
c ×7
c++ ×4
fall-through ×1
java ×1
optimization ×1
swift ×1
syntax ×1
while-loop ×1