switch 语句 - 修改 Duff 设备的语法 - 这是合法的 C/C++吗?
switch statement - Revising the syntax of Duff's device - Is this legal C/C++?
就在昨天晚上,我第一次遇到了好奇的达夫的设备。我读了一些这方面的资料,我觉得理解起来并不难。我好奇的是奇怪的语法(来自维基百科):
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);
}
}
我正在阅读一个switch语句的c++标准定义(如果它过时了,请告诉我,我不熟悉Open-Std.org)。据我所知,case语句只是简化的跳转语句,供switch语句使用。
switch本身完全忽略嵌套的do-while,循环忽略case语句。由于switch跳转到循环内部,因此循环被执行。开关的作用是覆盖剩余部分(被8整除的部分),循环处理可整除的部分。这一切都有意义。
我的问题是为什么语法这么别扭?我想到循环可以这样写所有的case语句都包含在里面,对吗?我在标准中没有看到任何禁止这种行为的内容,并且它在GCC 4.7下可以正确编译,因此以下内容被认为是合法的吗?
register short *to, *from;
register int count;
{
register int n = (count + 7) / 8;
switch (count <= 0 ? 8 : count % 8)
{
do
{
case 0: *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++;
default: ; // invalid count, suppress warning, etc.
} while(--n > 0);
}
}
对我来说,这使得代码的意图更加清晰。感谢您的任何反馈。;)
Edit:如下所述,原始代码是为C编写的,并且对于count和n变量具有隐式int。因为我把它标记为c++,所以我修改了它。
Edit 2:修改了修改后的示例代码,以考虑无效的计数值。
看看c++ 11标准,我想你问的那部分代码是允许的。你试过吗?
我认为最适用的规则是:
注意:通常,作为switch主题的子语句是复合的,
case
和default
标签出现在(复合)子语句中包含的顶级语句上,但这不是必需的。
实际上,这意味着您可以去掉do
- while
周围的大括号,并写入
int n = (count + 7) / 8;
switch (count % 8) do
{
case 0: *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);
然而,这一行是不合法的c++:
register n = (count + 7) / 8;
c++不允许default-int,必须指定或推断变量的类型。
哦,这里,在不破坏格式的情况下修复迭代次数:
int n = 1 + count / 8;
switch (count % 8) 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++;
case 0: ;
} while(--n > 0);
代码当然是合法的:完全没有关于块和/或循环的要求。值得注意的是,上面的循环不能正确处理count == 0
。但是,下面这个代码可以很好地处理它:
int count = atoi(ac == 1? "1": av[1]);
switch (count % 4)
{
case 0: while (0 < count) { std::cout << "0n";
case 3: std::cout << "3n";
case 2: std::cout << "2n";
case 1: std::cout << "1n";
count -= 4;
}
}
将case 0
标签放入循环中也会错误地执行嵌套语句。虽然我看到Duff的设备总是使用do-while
循环,但似乎上面的代码更自然地处理边界条件。
是的,这是合法的。switch
语句的标签通常与switch
语句写在同一层。但是,将它们写在复合语句中是合法的,例如在循环中间。
EDIT:没有要求switch语句体必须以标签开头,任何代码都是合法的。然而,没有办法从switch语句本身进入它,所以除非它是一个循环,或者一个普通的标签,否则代码将是不可访问的。
swtich
语句另一个有趣的地方是大括号是可选的。但是,在这种情况下,只允许使用一个标签:
switch (i)
case 5: printf("High fiven");
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 单独定义模板化嵌套类方法的正确语法
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 使用基类指针调用基类的值构造函数的语法是什么?
- 很好的语法来获取对向量/数组数据的大小引用?
- C++语法运算符功能?
- C++使用 rand 定义函数语法
- 什么文件可以修改 atom 的C++语法?
- 创建模板嵌套类实例的语法?
- C++语法差异:二维和一维数组(指针算术)
- 将信息输入到下面显示的结构向量中的正确语法/格式是什么