zoukankan      html  css  js  c++  java
  • C语言:if(0)之后的语句真的不会执行吗?

    C语言——if(0)之后的语句真的不会执行吗?

    原文(有删改):https://www.cnblogs.com/CodeWorkerLiMing/p/14726960.html

    前言

    学过c语言的都知道,通常:If(0)之后的代码是不执行的,网上也有详细的说明。

    近期在微信群中看到大佬们提到了Clifford's Device,由于一个比较冷门的c语言技巧,趁此学习下。

    这位大佬在文章也提到过Duff's Device,这个是比较出名的,他自己想出来一个switch case的代码框架(暂且如此称呼)。经过gcc编译运行,语法没有错。

    if(0)在goto语句中的应用

    goto是一个关键字,可以在函数内直接跳转到某个label处再执行,在某些场合是比较适合的,linux中也有用到(linus也是大神~)贴代码之前,上一个库函数的c语言例子先热热身。

    #include <stdlib.h>
    long int strtol(const char *str, char **endptr, int base)
    

    描述 把参数 str 所指向的字符串根据给定的 base 转换为一个长整数(类型为 long int 型),base 必须介于 2 和 36(包含)之间,或者是特殊值 0。

    参数解析:

    • str : 要转换为长整数的字符串。
    • endptr : 对类型为 char* 的对象的引用,其值由函数设置为 str 中数值后的下一个字符。
    • base :基数,必须介于 2 和 36(包含)之间,或者是特殊值 0。

    返回值:该函数返回转换后的长整数,如果没有执行有效的转换,则返回一个零值。

    测试代码

    /* strtol example */
    #include <stdio.h>      /* printf */
    #include <stdlib.h>     /* strtol */
    
    int main ()
    {
        char szNumbers[] = "2001 60c0c0 -1101110100110100100000 0x6fffff";
        char * pEnd;
        long int li1, li2, li3, li4;
        li1 = strtol (szNumbers,&pEnd,10);
        li2 = strtol (pEnd,&pEnd,16);
        li3 = strtol (pEnd,&pEnd,2);
        li4 = strtol (pEnd,NULL,0);
        printf ("The decimal equivalents are: %ld, %ld, %ld and %ld.
    ", li1, li2, li3, li4);
        return 0;
    }
    

    编译运行后:

    The decimal equivalents are: 2001, 6340800, -3624224 and 7340031.
    

    接下去,看看大佬的代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main (int argc, char** argv)
    {
        int num;
     
        if (argc != 3)
        {
            fprintf (stderr, "Usage: %s {BIN|OCT|DEC|HEX|STR} {ARG}
    ", argv[0]);
            return 1;
        }
     
        if (!strcmp (argv[1], "BIN") )
        {
            num = strtol (argv[2], NULL, 2);
            goto number_mode;
        }
        else if (!strcmp (argv[1], "OCT") )
        {
            num = strtol (argv[2], NULL, 8);
            goto number_mode;
        }
        else if (!strcmp (argv[1], "DEC") )
        {
            num = strtol (argv[2], NULL, 10);
            goto number_mode;
        }
        else if (!strcmp (argv[1], "HEX") )
        {
            num = strtol (argv[2], NULL, 16);
            goto number_mode;
        }
        else if (!strcmp (argv[1], "STR") )
        {
            printf ("Called with string argument: '%s'
    ", argv[2]);
        }
        else
        {
            printf ("Called unsupported mode: '%s'
    ", argv[1]);
        }
     
        /* Clifford's Device */
        if (0)
        {
    number_mode:
            printf ("Called with numeric argument: %d
    ", num);
        }
     
        return 0;
    }
    

    运行后:

    编译:
    gcc .Clifford-Device-goto.c -o .Clifford-Device-goto.exe
    无参数运行,提示报错
    .Clifford-Device-goto.exe
    Usage: Clifford-Device-goto.exe {BIN|OCT|DEC|HEX|STR} {ARG}
    带十六进制参数
     .Clifford-Device-goto.exe HEX 0x1234
    Called with numeric argument: 4660
    0x1234的确=4660
    代码测试完成!
    

    这个代码应该不难理解了,具体可以实际上机测试体验下。

    if(0)在switch中的应用

    这里使用了if(0),直接运行的效果如下:

    #include <stdio.h>
    #define IF_DEF  1
    
    #define MCASE((X),(SS)) if(0) {case X: SS }
    
    int main (void)
    {
        char* num;
    
        int argc_test;
    
        for (int i = 0; i < 7; i++)
        {
            argc_test = i;
    #if IF_DEF == 1
            printf ("if (0) %d
    " , argc_test);
            switch (argc_test - 1)
            {
                if (0) { case  0:
                    num = "zero";
                    printf ("==0
    ");
                }
                if (0)
                {
                case  2:
                    num = "two";
                    printf ("==2
    ");
                }
                if (0)
                {
                case  3:
                    num = "three";
                    printf ("==3
    ");
                }
                if (0)
                {
                case  4:
                    num = "four";
                    printf ("==4
    ");
                }
                if (0)
                {
                case  5:
                    num = "five";
                    printf ("==5
    ");
                }
                if (0)
                {
                default:
                    num = "many";
                    printf ("==...
    ");
                }
                printf ("Called with %s arguments.
    ", num);
                break;
            case 1:
                printf ("Called with one argument.
    ");
            }
    #else
            printf ("no if (0)
    ");
            switch (argc_test - 1)
            {
                //if (0)
                {
                case  0:
                    num = "zero";
                    printf ("==0
    ");
                }
                //if (0)
                {
                case  2:
                    num = "two";
                    printf ("==2
    ");
                }
                //if (0)
                {
                case  3:
                    num = "three";
                    printf ("==3
    ");
                }
                //if (0)
                {
                case  4:
                    num = "four";
                    printf ("==4
    ");
                }
                //if (0)
                {
                case  5:
                    num = "five";
                    printf ("==5
    ");
                }
                //if (0)
                {
                default:
                    num = "many";
                    printf ("==...
    ");
                }
                printf ("Called with %s arguments.
    ", num);
                break;
            case 1:
                printf ("Called with one argument.
    ");
            }
    #endif
        }
    
        return 0;
    }
    

    测试结果:

    if (0)
    ==...
    Called with many arguments.
    if (0)
    ==0
    Called with zero arguments.
    if (0)
    Called with one argument.
    if (0)
    ==2
    Called with two arguments.
    if (0)
    ==3
    Called with three arguments.
    if (0)
    ==4
    Called with four arguments.
    if (0)
    ==5
    Called with five arguments.
    

    部分代码已经做了修改,便于学习。

    是不是很疑惑?为何没有break,也没有被fall through

    原理,经过咨询大佬,原来switch-case类似于goto-label,难怪其效率是高于if() {} else if() {} else {}结构的。另外if(0)可以防止被fall through 对吧,等同于添加了break

    这下应该真相大白了,原来c语言还有这个操作,难以想象,具体的思想可以看原版英文。平时使用还是老老实实的按规范写代码,毕竟项目是需要维护的,而不是秀技巧的。

    如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
    若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
    博客地址:https://www.cnblogs.com/schips/
  • 相关阅读:
    Solaris 默认Shell 修改
    关系数组
    文件描述符 文件操作 <> open 文件句柄
    IO 双引号 输出 输入
    第五章答案
    子例程 subroutine
    钻石操作符
    花括号的使用 printf %${width}s , 否则会 去找 $widths
    print reverse <> 是打印全部的文件内容 ?
    hihoCoder#1239 Fibonacci
  • 原文地址:https://www.cnblogs.com/schips/p/if0_in_c-cpp.html
Copyright © 2011-2022 走看看