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.\n", 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}\n", 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'\n", argv[2]);
}
else
{
printf ("Called unsupported mode: '%s'\n", argv[1]);
} /* Clifford's Device */
if (0)
{
number_mode:
printf ("Called with numeric argument: %d\n", 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\n" , argc_test);
switch (argc_test - 1)
{
if (0) { case 0:
num = "zero";
printf ("==0\n");
}
if (0)
{
case 2:
num = "two";
printf ("==2\n");
}
if (0)
{
case 3:
num = "three";
printf ("==3\n");
}
if (0)
{
case 4:
num = "four";
printf ("==4\n");
}
if (0)
{
case 5:
num = "five";
printf ("==5\n");
}
if (0)
{
default:
num = "many";
printf ("==...\n");
}
printf ("Called with %s arguments.\n", num);
break;
case 1:
printf ("Called with one argument.\n");
}
#else
printf ("no if (0)\n");
switch (argc_test - 1)
{
//if (0)
{
case 0:
num = "zero";
printf ("==0\n");
}
//if (0)
{
case 2:
num = "two";
printf ("==2\n");
}
//if (0)
{
case 3:
num = "three";
printf ("==3\n");
}
//if (0)
{
case 4:
num = "four";
printf ("==4\n");
}
//if (0)
{
case 5:
num = "five";
printf ("==5\n");
}
//if (0)
{
default:
num = "many";
printf ("==...\n");
}
printf ("Called with %s arguments.\n", num);
break;
case 1:
printf ("Called with one argument.\n");
}
#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语言还有这个操作,难以想象,具体的思想可以看原版英文。平时使用还是老老实实的按规范写代码,毕竟项目是需要维护的,而不是秀技巧的。

C语言:if(0)之后的语句真的不会执行吗?的更多相关文章

  1. 【C语言】-选择结构-if语句

    if语句:也可称条件语句,是根据所给定条件的值是真还是假决定执行不同的分支. if语句有单分支.双分支.多分支以及if语句的嵌套等多种形式. 单分支if语句: if (条件表达式) { 语句组1; } ...

  2. Go语言规格说明书 之 select语句(Select statements)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  3. Python语言学习前提:条件语句

    一.条件语句 1.条件语句:通过一条或多条语句的执行结果(True或False)来决定执行额代码块.python程序语言指定任何非0或非空(null)的值为true,0或null为false. 2. ...

  4. iOS -Swift 3.0 -for(循环语句用法)

    // // ViewController.swift // Swift-循环语句 // // Created by luorende on 16/12/08. // Copyright © 2016年 ...

  5. 李洪强漫谈iOS开发[C语言-038]-if else if语句

    李洪强漫谈iOS开发[C语言-038]-if else if语句

  6. C语言本身并不提供输入输出语句

    C语言本身并不提供输入输出语句,输入和输出操作是由函数来实现的.在C标准函数库中提供了一些输入输出函数,例如,printf函数和scanf函数.在使用他们时,千万不要误认为他们是C语言提供的“输入输出 ...

  7. 网络1911、1912 C语言第0次作业批改总结

    网络1911.1912 C语言第0次作业批改总结 题目:C博客作业00--我的第一篇博客 一.评分规则 总分10分,每个问题都务必回答,分值都在问题后面 抄袭 - 0分 博客作业格式不规范,没有用Ma ...

  8. Python语言学习前提:循环语句

    一.循环语句 1.循环语句:允许执行下一个语句或语句组多次 2. 循环类型 3. 循环控制语句 4. while 循环语句 a.while循环语句:在某个条件下,循环执行某段程序,以处理需要重复处理的 ...

  9. 【Java】面试官灵魂拷问:if语句执行完else语句真的不会再执行吗?

    写在前面 最近跳槽找工作的朋友确实不少,遇到的面试题也是千奇百怪,这不,一名读者朋友面试时,被面试官问到了一个直击灵魂的问题:if 语句执行完else语句真的不会再执行吗?这个奇葩的问题把这名读者问倒 ...

  10. Go语言学习——函数二 defer语句

    函数 package main import "fmt" // 函数:一段代码的封装 func f1(){ fmt.Println("Hello 中国!") } ...

随机推荐

  1. 2021~2022Apache大数据相关项目盘点

    一.晋升为Apache TLP(Top-Level Project)的大数据相关项目 1.1.Apache DataSketches (20210203) 1.2.Apache Gobblin (20 ...

  2. Spire.Doc 生成长图

    按模板生成内容,转换成长图保存: Document doc = new Document("A_BizRpt.docx"); ....... Image[] imgs = doc. ...

  3. sqli-labs-master 导入导出 + 第七关

    1.load_file()导出文件 load_file(file_name):读取文件并返回该文件内容作为一个字符串. 使用条件: A:必须有权限读取并且文件完全可读 B:预读取文件必修在服务器上 C ...

  4. three.js案例-web3d三维地图大屏炫酷3D地图下钻地图-附源码

    炫酷3D地图效果如下: 代码注释非常详细: create() { // 添加雾,随着距离线性增大,只能看到一个小是视野范围内的场景,地图缩小很多东西就会看不清 //this.scene.fog = n ...

  5. 每天上一当系列之vue修饰符.number

    今天使用number修饰符去处理el-input的内容为数字做校验原本以为省事不少,没想到,为0开头无法输入第二位以后,并且输入的比较多的时候会出现Infinity 很神奇,网上查了说是element ...

  6. JDK源码阅读-------自学笔记(八)(数组演示冒泡排序和二分查找)

    冒泡排序 算法 比较相邻的元素.如果第一个比第二个大,就交换他们两个 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数 针对所有的元素重复以上的步骤,除 ...

  7. 内网渗透 Metasploit(MSF)基础使用

    免责申明 以下内容仅供学习使用,非法使用造成的问题由使用人承担 攻击思路 漏洞探测(信息收集) <- fsacn,namp | 漏洞利用 <- 工具(msf等) | 获取服务器权限 MSF ...

  8. centos7下xfs文件系统的备份和恢复:完全备份,增量备份,差异备份

    目录 一.关于xfs文件系统 二.xfsdump的备份级别和注意事项 三.完全备份整个目录/分区,然后恢复数据 四.完全备份分区中某个目录,然后恢复某个文件/文件夹 五.增量备份 一.关于xfs文件系 ...

  9. 把nacos安装成windows服务

    方式一: 用sc的方式安装和删除服务 摘自:https://blog.csdn.net/qq_33803102/article/details/109024989 sc create nacos st ...

  10. 【源码阅读】消息队列之DoNetMQ的初步了解

    这个组件,是一个分布式的组件,好处就是,不怕消息太多了,都挤在一个服务器上,出现服务器内存不够的情况.服务器内存不够用的问题解决了,但是如果消费队列要进行数据库的操作,那么性能瓶颈将出现在数据库上,如 ...