代码之家  ›  专栏  ›  技术社区  ›  Chi_Iroh Chris Dodd

切换(…)while(0)有什么意义?

  •  0
  • Chi_Iroh Chris Dodd  · 技术社区  · 3 年前

    我最近发现 switch (...) while (0) {} 在C中是合法的( here ),但我找不到关于这件事的解释。
    我唯一一次在互联网上看到这个是在 obfuscation GitHub repository ,没有任何解释。

    很明显,我所有的研究都给了我关于while或switch循环的结果,甚至没有提到这个语法,所以我想这更多的是合法的,但非常罕见,可能毫无用处,是对标准的滥用。 有人能帮我理解吗?

    编辑: 正如@phuclv answer中所解释的,switch语句后面需要一个select语句,它可以是内部有一些代码的括号(在这种情况下…可能是case语句),也可以是有自己括号的循环等,这意味着这在C中是合法的:

    switch (...) while (...) switch (...) {}
    

    switch 根本不关心后面的语句,它似乎只查找case和/或default。

    switch (1) while (0) {
        puts("Not executed");
    }
    

    这个 puts 语句并没有被执行,因为并没有case/default,所以这里的开关基本上是无用的。 你可以在上面看到 Compiler Explorer ,GCC发出警告并拆下开关。

    但是,请注意:

    #include <stdio.h>
    
    int main(void) {
        switch (1) while (1) switch (0) {
            case 1:
            puts("hello");
        }
    }
    

    由于开关(1)没有案例1或默认语句,因此不会显示任何内容,程序会立即退出。 如果我们加一个:

    switch (1) case 1: while (1) switch (0)
    

    程序无限循环,因为嵌套最多的循环是switch(0),没有大小写0或默认值。

    结论: while (0) 这只是一种滥用,除了混淆之外没有任何用处,但这仍然是一件有趣的事情。

    1 回复  |  直到 3 年前
        1
  •  8
  •   phuclv    3 年前

    在C标准中,语句被定义为以下语句之一

    A.2.3 Statements

    (6.8)声明:

    labeled-statement
    compound-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement
    

    switch 是 selection-statement 定义为具有如下语法

    (6.8.4)选择声明:

    if ( expression ) statement
    if ( expression ) statement else statement
    switch ( expression ) statement
    

    所以 转换 接收 expression 然后做 statement ,通常是 compound-statement {} 但它可以是任何语句,包括 iteration-statement

    (6.8.2)复合语句:

    { block-item-listopt }
    

    (6.8.5)迭代语句:

    while ( expression ) statement
    do statement while ( expression ) ;
    for ( expressionopt ; expressionopt ; expressionopt ) statement
    for ( declaration expressionopt ; expressionopt ) statement
    

    转换 语句跳转到 labeled-statement (这也是一个正常的语句),并且它不关心子语句中的内容,编译器只会生成一个计算跳转到 case 匹配 表示

    (6.8.1)标记语句:

    identifier : statement
    case constant-expression : statement
    default : statement
    
        2
  •  0
  •   Luis Colorado    3 年前

    基本上,施工

    switch(expr) while (cond) {
    }
    

    应该几乎等同于:

    while(cond) {
        switch(expr) {
        }
    }
    

    除了以下顺序 cond 和 expr 评估。

    只需检查以下代码:

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
        switch(random() % 6) while(1) {
            case 0: printf("You got a one(1)\n");
            case 1: printf("You got a two(2)\n");
            case 2: printf("You got a three(3)\n");
            case 3: printf("You got a four(4)\n");
            case 4: printf("You got a five(5)\n");
            case 5: printf("You got a six(6)\n");
        }
    }
    

    当运行时,它会给你以下信息:

    You got a four(4)
    You got a five(5)
    You got a six(6)
    You got a one(1)
    You got a two(2)
    You got a three(3)
    You got a four(4)
    You got a five(5)
    You got a six(6)
    You got a one(1)
    ...
    

    编辑

    恐怕我的帖子的输出实际上并不是很随机:)所以,恐怕等价性远非真实。

    在对照检查后 while(cond) switch(expr) 我得到了一个或多或少的随机序列,所以出于某种原因 expr 在使用前一个构造时未完全评估。

    在对照检查后 switch(expr) while(cond) 我没有随机性,因为 random() 只计算一次,并产生所示的输出(第一个随机数恰好是0,选择第一个情况,然后依次选择所有其他情况,循环回 while 环在这种情况下,使用 break; 中的开关没有用,因为它会脱离循环,使您看到行为(循环执行直到 打破 语句,退出循环)