深入理解C语言的逻辑控制

本文对C语言的逻辑控制做一番较为深入的探讨,一般来说C语言的逻辑控制语句主要有如下的7种:

1、 goto 最强大,但一般只在特殊环境下使用。
2、 if else
3、 ?:
4、 switch case
5、 for
6、 while
7、 do while

自从dijkstra的论文Go To Statement Considered Harmful以后,C语言代码很少看到goto了。(一般用在多次资源分配的错误处理上)
但,从计算机的角度来说,缺少goto(jmp指令)还真没法干活。其实,goto是最符合我们的设计流程图的。
将一个流程图用goto来实现也最直观。goto能真正让我们做到心之所动,剑之所至。

接下来,分别考虑将2-7转化为对应的goto语言版本(等价于转化为对应汇编版本)。

2、if语句

if (条件1)
//代码块1
else
//代码块2

对应goto:

t = 条件1;
if (t为真)goto true;
//代码块2
goto finish
true:
//代码块1
finish:

3、?: 和if else是等价的

只不过if语句为代码块,?:为表达式。

变量= (条件1)? 表达式1:表达式2;

goto版本:

t = 条件1;
if (t为真)
goto true;
//变量=表达式2
goto finish;
true:
//变量=表达式1
finish:

注意:?:里面的表达式尽量简单,过于复杂的话,改用if语句实现,这样方便调试。

4、switch-case

switch (条件取值变量)
case 元素1 :
//语句块1;
break;
case 元素2:
//语句块2;
break;
...
case 元素N
//语句块N;
break;
default:
//默认处理。
break;
}

goto版本:

跳转表={标签1,标签2,...,标签N }
goto 跳转表[元素index]
//标签1:
//语句块1
goto Finish
//标签2:
//语句块2
goto Finish
...
//标签N:
//语句块N
goto Finish
default:
//默认处理。
Finish:

5、for语句

for (初始化语句;判断语句;迭代语句)
//循环语句块

goto版本:

//初始化语句;
if (判断语句为否)
goto Finish;
loop:
//循环语句块
//迭代语句
if (判断语句为真)
goto loop;
Finish:

6、while语句

while(条件为真)
//代码块
//迭代块

对应goto版本:

loop:
t = 条件
if (不为真) goto Finish;
//代码块
//迭代块
Finish:

7、do-while语句

do {
//语句块1
//迭代块1
} while (条件为真)

goto版本:

loop:
//语句块1
//迭代块1
if (条件为真) goto loop;

C语言的goto同汇编语句jmp系列指令逻辑上是完全一致的。

注意:

1、 关于条件,有个经典的逻辑代数公式:
摩根公式:
!(A && B) = (!A) || (!B)
建议,对复杂逻辑,手动画代数运算表
A B 结果
0 0 ?
0 1 ?
1 0 ?
1 1 ?
并保证单体测试的全覆盖。

2、 逻辑操作和位操作是2组,需要区分开来。
与 或 反
逻辑: && || !
位: & | ~ ^ (异或)

3 强烈推荐在写代码前,在纸上画完整的流程图,梳理自己的设计思路。

(0)

相关推荐

  • 从汇编看c++中变量类型的深入分析

    全局变量的生命期和可见性是整个程序的运行期间,下面就来用汇编来看一下实际情况: c++源码: 复制代码 代码如下: int i = 2;//全局变量 int main() {    int j = i;} 下面是汇编代码: 复制代码 代码如下: PUBLIC    ?i@@3HA                        ; i_DATA    SEGMENT?i@@3HA    DD    02H                    ; 全局变量i内存空间_DATA    ENDSPUB

  • C语言中判断int,long型等变量是否赋值的方法详解

    当然,如果你不赋值给局部变量,这样会导致整个程序的崩溃,因为,它的内容被系统指向了垃圾内存.下面我们看一段代码: 复制代码 代码如下: #include <stdio.h>#include <string.h>#include <stdlib.h>int globle_value;int my_sum(int value1, int value2);long my_sub(long value1, long value2);int main(void){ int aut

  • c语言二进制数按位输出示例

    提出问题: 1.输入int 20,其二进制为10100,按位输出10100; 2.或者将1转化为"+",0转化为"-",输出就是" + - + - - "; 解决方法: 复制代码 代码如下: int biTofh(int bi,int len){//二进制转化为正负号        int i=0;        while(i<len){                int tmp = 1;                if((bi

  • 深入探讨C语言中局部变量与全局变量在内存中的存放位置

    C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register) 1.局部变量和全局变量在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放.这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了.这种变量有效性的范围称变量的作用域.不仅对于形参变量,C语言中所有的量都有自己的作用域.变量说明的方式不同,其作用域也不同.C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量.1.1局部变量局部变量也称为内部变量

  • C语言实现单链表逆序与逆序输出实例

    单链表的逆序输出分为两种情况,一种是只逆序输出,实际上不逆序:另一种是把链表逆序.本文就分别实例讲述一下两种方法.具体如下: 1.逆序输出 实例代码如下: #include<iostream> #include<stack> #include<assert.h> using namespace std; typedef struct node{ int data; node * next; }node; //尾部添加 node * add(int n, node * h

  • C++空类及没有成员变量的类的大小实例分析

    众所周知的C++中空类的大小为1,但是除了空类之外的其他一些没有成员变量的类的大小,还是有相当一部分开发人员对此有很多不明之处的. 这里我们以如下代码为例: #include using namespace std; class a {}; class b{}; class c :public a{ virtual void fun() = 0; }; class d :public b, public c{}; int main() { cout << "sizeof(a)&quo

  • c语言全局变量和局部变量问题及解决汇总

    1.局部变量能否和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,需要使用"::" 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量.对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内. 2.如何引用一个已经定义过的全局变量? 答:extern 可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全

  • C语言变量类型与输出控制用法实例教程

    本文实例讲述了C语言变量类型与输出控制用法,有助于读者很好的对其进行总结与归纳.该实例分享给大家供大家参考借鉴之用.具体如下: 完整实例代码如下: /********************************************** **<Beginning C 4th Edition>Notes codes ** Created by Goopand ** Compiler: gcc 4.7.0 *******************************************

  • c++作用域运算符用法(全局变量和局部变量)

    通常情况下,如果有两个同名变量,一个是全局变量,另一个是局部变量,那么局部变量在其作用域内具有较高的优先权,它将屏蔽全局变量. 作用域运算符 复制代码 代码如下: #include<iostream>using namespace std;int num=10;int main(){   int num;    num=25;    cout<<"num is "<<num<<endl;    return 0;} 程序的输出结果是num

  • c++静态局部变量和静态函数示例

    在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存.但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效.但有的时候我们需要在两次调用之间对变量的值进行保存.通常的想法是定义一个全局变量来实现.但是这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便.静态局部变量正好可以解决这个问题.静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值.该变量在全局数据区内分配内存:静态局部变量在程序执行到该对象的声明

  • vc6.0中c语言控制台程序中的定时技术(定时器)

    打开main.c编译运行,注意,打开main.c之后一定要将win32timer.c也加进工程中一起编译,下面有图.在开发单片机.ARM以及Linux系统的程序时,因为硬件定时中断的存在我们很方便构造出定时ISR,然而在VC6.0中,我们如何写一个定时程序呢?其实,就是timeSetEvent()这个函数的调用.这个函数的解释见MSDN.详细原理,请看我代码中的注释,我写得很详细了. main.c 复制代码 代码如下: //======================// main.c//===

  • C++调试追踪class成员变量的方法

    比如:int (*foo)(int arg),记住要和另一个指针函数区分开来,类似这样:int *foo(int arg).比如我们可以这样声明一个变量和函数: 复制代码 代码如下: int (*pfun)(int arg)=0;int fun(int arg);    //这个函数实现随便啦,我就不写了. 如果我们想利用函数指针操作函数,就和指针变量使用一样: 复制代码 代码如下: pfun=fun;int result=(*pfun)(123); 对,很鸡肋也没必要.这是当然,因为我们没用在

随机推荐