C语言基础知识

1、在数据流图中,用标有名字的带箭头线段表示数据流。在程序流程图中,用标有名字的带箭头线段表示控制流。

2、结构化程序设计思想包括:自顶向下、逐步求精、模块化、限制使用goto语句,多态性是面向对象的程序设计的思想。

3、软件设计中,模块划分应遵循的准则是高内聚低耦合、模块大小规模适当、模块的依赖关系适当等。

4、可行性分析阶段产生可行性分钟报告。总体设计阶段产生概要设计说明书。集成测试计划是在概要设计阶段编写的文档。需求规格说明书是需求分析阶段产生的主要文档,是后续工作如设计、编码等需要的重要参考文档。

5、算法原则上能够精确的运行,而且人们用笔和纸做有限次运算后即可完成。算法的有穷性是指算法程序的运行时间是有限的。

算法是指解题方案的准确而完整的描述,算法既不等于程序,也不等于计算方法。设计算法时不仅要考虑对数据对象的运算和操作,还要考虑算法的控制结构。

6、快速排序、冒泡排序和直接插入排序在最坏情况下,比较次数都是n(n-1)/2,堆排序在最坏情况下的比较次数最少,是O(log2n)。

7、栈是只允许在同一端进行插入和删除运算的线性表,按“先进后出”组织数据。

8、将E-R图转换成关系图数据模型是把图形分析出来的联系反映到数据库中,即设计出表,因此属于逻辑设计阶段。

9、自然连接是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是相同属性组,并且在结果中把重复的属性列去掉。

笛卡尔积是用R集合中的元素为第一元素,S集合中的元素为第二元素构成的有序对。

在除运算中T的域由R中那些不出现在S中的域所组成,对于T中的任一有序组,由它与关系S中每个有序组所构成的有序组均出现在关系R中。

2、队列的顺序存储结构一般采用循环队列的形式。循环队列需要队头和队尾两个指针来共同反映队列中元素的动态变化,是线性结构。

3、当有序线性表为顺序存储时才能用二分法,对于长度为n的有序线性表在最坏的情况下,二分法需要比较log2n次,而顺序查找需要比较n次。

4、链式存储结构既可以针对线性结构也可以针对非线性结构,每个结点都由数据域与指针域两部分组成,增加了存储空间。

5、在需求分析阶段可以使用的工具有数据流图(DFD图),数据字典(DD),判定树与判定表。需求分析阶段的工作可以概括为:需求获取、需求分析、编写需求规格说明书、需求评审四个方面。

6、在面向对象方法中,对象的基本特点包括:标识唯一性、分类性、多态性、封装性、模块独立性好。

7、数据管理技术的三个阶段:人工管理阶段、文件系统阶段和数据库系统阶段。其中最后一个阶段结构简单,逻辑性强物理性少,使用方便,在各个表现都好,一直占据数据库领域的主导地位。

1、栈支持子程序的调用。

2、在任意一棵二叉树中,度为0的叶子结点总是比度为2的结点多一个。 在非空二叉树中,第一层的结点总数不超过2的n-1次方

深度为h的二叉树最多有2的h次方减1个结点,最少有h个结点。 具有n个结点的完全二叉树的深度为log2(n+1)。

和树的区别:树中结点的最大度没有限制,而二叉树结点的最大度数为2;树的结点左右之分,而二叉树的结点有左右之分,是非线性结构。

3、编译程序、操作系统、汇编程序、网络软件、数据库管理系统都属于系统软件,只有教务系统、学生成绩管理系统等才是应用软件。

4、软件测试的目的是为了发现错误而执行程序的过程,并不涉及改正错误。程序调试的基本步骤有:错误定位、修改设计和代码以排除错误、进行回归测试以防止引进新的错误。程序调试通常被称为Debug,即排错。软件测试的基本准则:所有的测试都应追溯到需求、严格执行错误计划,排除测试的随意性,充分注意测试中的群集现象,程序员应避免检查自己的程序,不可能实现穷举测试,妥善保存测试计划等。

5、数据库应用系统中的核心问题是设计一个能满足用户需求、性能良好的数据库,这就是数据库设计。

6、投影运算是从关系模式中挑选若干属性组成新的关系,这是从列的角度进行的运算,相当于对胡咯一进行垂直分解。

7、模块独立性是指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少且接口简单。耦合性是模块间互相连接的紧密程度的度量,内聚性是指一个模块内部各个元素彼此结合的紧密程度。

8、数据库应用系统中的核心问题是设计一个能满足用户需求、性能良好的数据库,这就是数据库设计。

9、投影运算是从关系模式中挑选若干属性组成新的关系,这是从列的角度进行的运算,相当于对关系进行垂直分解。

1、数据字典的重要作用是作为需求分析阶段的工具。

2、数据库的三级模式分为:概念模式、内模式和外模式。

概念模式是数据库系统中全局数据逻辑结构的描述,是用户的公共数据视图。 外模式也称子模式或用户模式,它是用户的数据视图,给出了每个用户的局部数据描述。

内模式又称物理模式,它给出了数据库的物理存储结构与物理存取方法。

层次模型、网状模型和关系模型是目前数据库中最常用的三种数据模型,划分它们的原则是数据之间的联系方式。

层次模型用树形结构表示各实体与实体间的联系,网状模型用网状结构,关系模型用表格形式表示;有以下几方面的优点:数据结构比较简单、具有很高的数据独立性、可以直接处理多对多的联系,以及有坚实的理论基础。

3、面向对象方法的主要特征包括继承、封装和多态。

面向对象方法是一种作用对象、类、封装、继承、多态和消息等概念来构造、测试、重构软件的方法。面向对象方法从对象出发,发展出对象、类、消息、继承等概念。

4、自顶向下、模块化和逐步求精是结构化设计的主要特征。

5、循环链表和双向链表都是线性结构,有一个以上跟结点的结构一定是非线性结构。

6、继承是面向对象的方法的一个主要特征,是使已有的类的定义作为基础建立新类的定义技术。广义的说,继承是指能够直接获得已有的性质和特征,而不必重复定义他们,因此继承是指类之间的共享属性和操作的机制。

7、通常,将软件产品从提出、实现、使用维护到停止使用退役的过程称为软件生命周期。也就是说,软件产品从考虑其概念开始,到该软件产品不能使用为止的

整个时期都属于软件生命周期。

8、简单的程序设计一般包括:确定数据结构、确定算法、编码、在计算机上调试程序、整理并写出文档资料。

9、详细设计的任务是软件结构中而非总体结构图中的每一个模块确定实现算法和局部数据结构,用某种选定的表达工具表示算法和数据结构的细节。

10、数据定义语言:负责数据的模式定义与数据的物理存取构建;数据操纵语言:负责数据的操纵,包括查询及增加、删除、修改等操作;数据控制语言:负责数据完整性、安全性的定义与检查以及并发控制、故障恢复等功能。

1、一般来说,在线性表的链式存储结构中,各数据结点的存储序号是不连续的,并且各结点在存储空间中的位置关系与逻辑关系也不一致。线性链表中的数据插入和删除都不需要移动表中的元素,只需改变结点的指针域即可。

2、实体完整性约束要求关系的主键中属性值不能为空值。

3、软件危机主要表现在:软件需求的增长得不到满足;软件开发成本和进度无法控制;软件质量难以保证;软件不可维护或维护程度非常低;软件的成本不断提高;软件开发生产率的提高赶不上硬件的发展和应用需求的增长。

4、黑盒测试是对软件已经实现的功能是否满足需求进行的测试和验证,黑盒测试完全不考虑程序内部的逻辑结构和内部特性,只根据程序的需求和功能规格说明,检查程序的功能是否符合它的功能规格说明。

5、系统结构图是对软件系统结构的总体设计的图形显示。在需求分析阶段,已经从系统开发的角度出发,把系统按功能逐次分割成层次结构,是在概要设计阶段用到的。PAD图是在详细设计设计阶段用到的。程序流程图是对程序流程的图形显示,在详细设计过程中用到。数据流图(DFD图)是结构化分析方法中使用的工具,它以图形的方法描述数据在系统中流动和处理的过程,由于它只反映必须完成的逻辑功能,因此它是一种功能模型,是在可行性研究阶段用到的而非软件设计时用到。

6、算法的时间复杂度是指算法在计算机内执行时所需时间的度量。空间复杂度是指算法在计算机内执行时所需存储空间的度量。

7、栈和队列都是一种特殊的操作受限的线性表,只允许在端点处进行插入和删除。而栈只允许在线性表的一端进行插入操作,另一端进行删除操作。其中允许插入的一端称为队尾,允许删除的一端称为队首。

8、利用信息隐蔽性,可以确保每一个模块的独立性。

9、模块之间的耦合程度反映了模块的独立性,也反映了系统分解后的复杂程度。按照耦合程度从强到弱分别是:内容耦合、公共耦合、外部耦合、控制耦合、标记耦合、数据耦合和非直接耦合,没有异构耦合这种方式。

10、在实体--联系模型中,用属性来描述现实世界中对象的属性所表示的对象的性质、特征和行为。

1、关系表中,每一行称为一个元组,对应表中的一条记录;每一列称为一个属性,对应表中的一个字段;在二维表中凡能唯一标识元组的最小属性集称为该表的键或码。

2、二叉树的遍历:首先访问根结点,然后遍历左子树,最后遍历右子树。并且在遍历左右子树时,上述规则同样适用,即“根-左-右”。

3、结构化程序设计强调的是程序的易读性。

4、总体设计过程通常由两个主要阶段组成:系统设计,确定系统的具体实现方案;结构设计,确定软件结构。为确定软件结构,首先需要从现实角度把复杂的功能进一步分解。分析员结合算法仔细分析数据流图中的每个处理,如果一个处理的功能过分复杂,必须把它的功能适当的分解成一系列比较简单的功能。

5、数据流图DFD是结构化分析方法最主要的一种图形工具,不属于过程设计工具。

6、在关系数据中,一个表就是一个关系,关系数据库管理系统管理的关系就是多个二维表。

 

第二篇:C语言基础知识重点和难点

C语言基础知识重点和难点

一、            数组

1.  一维数组的定义与初始化

1)   不能在方括号中用变量来表示元素的个数,但是可以是符号常数或常量表达式。

例如:

    #define FD 5

        main()

       {

        int a[3+2],b[7+FD];

        ……

}

是合法的。

但是下述说明方式是错误的。

    main()

        {

         int n=5;

         int a[n];

         ……

}

2)   C语言对数组的初始化赋值还有以下几点规定:

(1)       可以只给部分元素赋初值。

当{ }中值的个数少于元素个数时,只 给前面部分元素赋值。

例如:

    int a[10]={0,1,2,3,4};

表示只给a[0]~a[4]5个元素赋值,而后5个元素自动赋0值。

(2)  只能给元素逐个赋值,不能给数组整体赋值。

例如给十个元素全部赋1值,只能写为:

    int a[10]={1,1,1,1,1,1,1,1,1,1};

而不能写为:

    int a[10]=1;

(3)  如给全部元素赋值,则在数组说明中,可以不给出数组元素的个数。

例如:

    int a[5]={1,2,3,4,5};

可写为:

    int a[]={1,2,3,4,5};

2.  一维数组元素的引用

1)   在C语言中只能逐个地使用下标变量,而不能一次引用整个数组。

例如,输出有10个元素的数组必须使用循环语句逐个输出各下标变量:

    for(i=0; i<10; i++)

           printf("%d",a[i]);

而不能用一个语句输出整个数组。

下面的写法是错误的:

printf("%d",a);

2)   引用数组元素时一定注意下标不能越界

例如,int i=4, n[]={0,0,0,0,0};,

则可以引用n[0],n[4],n[!5],n[i++],但不能引用n[5], n[++i]

例1:若有定义语句:int m[ ]={5,4,3,2,1},i=4; ,则下面对m数组元素的引用中错误的是___C___。

     A、m[--i]

     B、m[2*2]

     C、m[m[0]]

     D、m[m[i]]

3.  一维数组的典型算法

1)   查找指定的元素,返回其下标。比如,要求查找数值5是否数组中

2)   查找数组的最大(最小)值,并返回最大(最小)值及其对应的下标

3)   数组的排序(升序或降序),包括冒泡排序和选择排序两种算法

4)   在有序数组中插入一个元素,使得数组仍然有序

5)   数组的逆序

6)   在数组中删除满足某条件的元素

4.  二维数组的初始化

二维数组初始化也是在类型说明时给各下标变量赋以初值。二维数组可按行分段赋值,也可按行连续赋值。

例如对数组a[5][3]:

1)     按行分段赋值可写为:

        int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} };

2)   按行连续赋值可写为:

        int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};

对于二维数组初始化赋值还有以下说明:

1)   可以只对部分元素赋初值,未赋初值的元素自动取0值。

        例如:

        int a[3][3]={{1},{2},{3}};

    是对每一行的第一列元素赋值,未赋值的元素取0值。 赋值后各元素的值为:

        1 0 0

2 0 0

3 0 0

int a [3][3]={{0,1},{0,0,2},{3}};

赋值后的元素值为:

    0 1 0

0 0 2

3 0 0

2)   如对全部元素赋初值,则第一维的长度可以不给出。

        例如:

    int a[3][3]={1,2,3,4,5,6,7,8,9};

可以写为:

int a[][3]={1,2,3,4,5,6,7,8,9};

例1:以下不能正确定义二维数组的选项是___D___。

     A、int a[2][2]={{1},{2}};

     B、int a[][2]={1,2,3,4};

     C、int a[2][2]={{1},2,3}

     D、int a[2][]={{1,2},{3,4}}

5.  二维数组元素的引用

和一维数组一样,一定要注意下标不越界。

例1:若有定义

  int  a[2][3];

以下选项中对a数组元素正确引用的是___D___

A)a[2][!1]    B)a[2][3]    

C)a[0][3]    D)a[1>2][!1]

6.  字符数组的初始化

1)   字符数组也允许在定义时作初始化赋值。

例如:

    char c[10]={‘c’, ‘  ’, ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,’m’};

赋值后各元素的值为:

    数组C    c[0]的值为‘c’

c[1]的值为‘ ’

c[2]的值为‘p’

c[3]的值为‘r’

c[4]的值为‘0’

c[5]的值为‘g’

c[6]的值为‘r’

c[7]的值为‘a’

c[8]的值为‘m’

其中c[9]未赋值,由的值为‘p’系统自动赋予0值。

当对全体元素赋初值时也可以省去长度说明。

例如:

    char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};

这时C数组的长度自动定为9。

在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。前面介绍字符串常量时,已说明字符串总是以'\0'作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符'\0'存入数组,并以此作为该字符串是否结束的标志。有了'\0'标志后,就不必再用字符数组的长度来判断字符串的长度了。

2)   C语言允许用字符串的方式对数组作初始化赋值。

例如:

    char c[]={'c', ' ','p','r','o','g','r','a','m'};

可写为:

        char c[]={"C program"};

    或去掉{}写为:

        char c[]="C program";

用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志'\0'。上面的数组c在内存中的实际存放情况为:

    ‘\0'是由C编译系统自动加上的。由于采用了‘\0'标志,所以在用字符串赋初值时一般无须指定数组的长度, 而由系统自行处理。

7.  字符串处理函数

用于输入输出的字符串函数,在使用前应包含头文件"stdio.h",使用其它字符串函数则应包含头文件"string.h"。

1)  输出函数 puts

2)  输入函数gets:gets读入字符串时,可以读入其中的空格,直到回车。而用scanf读入字符串时,遇到空格即停止。

3)  连接函数strcat:格式为strcat (字符数组名1,字符数组名2),一定注意,字符数组1一定要足够大,否则将越界。

4) 拷贝函数strcpy:格式为strcpy (字符数组名1,字符数组名2)。注意,字符数组赋值,不能用等于号,而要用strcpy函数

5) 比较函数strcmp:格式为strcmp(字符数组名1,字符数组名2)。注意,字符数组的比较不能用大于、小于号比较。

测字符串长度函数strlen:测字符串的实际长度(不含字符串结束标志‘\0’) 并作为函数返回值。


二、            函数

1.  形式参数和实际参数

函数的形参和实参具有以下特点:

1)   形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

2)   实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。

3)   实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。

4)   函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

下例可以说明这个问题。

int s(int n)

{

    int i;

    for(i=n-1;i>=1;i--)

      n=n+i;

    printf("n=%d\n",n);

}

main()

{

    int n;

    printf("input number\n");

    scanf("%d",&n);

    s(n);

    printf("n=%d\n",n);

}

2.  数组作为函数参数

1) 数组元素作函数实参

数组元素就是下标变量,它与普通变量并无区别。 因此它作为函数实参使用与普通变量是完全相同的,在发生函数调用时,把作为实参的数组元素的值传送给形参,实现单向的值传送。

2) 数组名作为函数参数

数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。

上图说明了这种情形。图中设a为实参数组,类型为整型。a占有以2000为首地址的一块内存区。b为形参数组名。当发生函数调用时,进行地址传送,把实参数组a的首地址传送给形参数组名b,于是b也取得该地址2000。于是a,b两数组共同占有以2000为首地址的一段连续内存单元。从图中还可以看出a和b下标相同的元素实际上也占相同的两个内存单元(整型数组每个元素占二字节)。例如a[0]和b[0]都占用2000和2001单元,当然a[0]等于b[0]。类推则有a[i]等于b[i]。

例1:判别一个整数数组中各元素的值,若大于0 则输出该值,若小于等于0则输出0值。编程如下:

void nzp(int a[5])

{

    int i;

    printf("\nvalues of array aare:\n");

    for(i=0;i<5;i++)

    {

      if(a[i]<0)a[i]=0;

      printf("%d ",a[i]);

    }

}

main()

{

    int b[5],i;

    printf("\ninput 5 numbers:\n");

    for(i=0;i<5;i++)

      scanf("%d",&b[i]);

    printf("initial values of array b are:\n");

    for(i=0;i<5;i++)

      printf("%d ",b[i]);

    nzp(b);

    printf("\nlast values of array b are:\n");

    for(i=0;i<5;i++)

      printf("%d ",b[i]);

}

3) 用数组名作为函数参数时应注意以下几点:

         i.      形参数组和实参数组的类型必须一致,否则将引起错误。

       ii.      形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程序执行结果将与实际不符,这是应予以注意的。

      iii.      在函数形参表中,允许不给出形参数组的长度,或用一个变量来表示数组元素的个数。

例如,可以写为:

void nzp(int a[])

或写为

void nzp(int a[],int n)

其中形参数组a没有给出长度,而由n值动态地表示数组的长度。n的值由主调函数的实参进行传送。

例1可改为例2的形式。

例2:

void nzp(int a[],int n)

{

    int i;

    printf("\nvalues of array a are:\n");

    for(i=0;i<n;i++)

      {

  if(a[i]<0) a[i]=0;

  printf("%d ",a[i]);

      }

}

main()

{

    int b[5],i;

    printf("\ninput 5 numbers:\n");

    for(i=0;i<5;i++)

      scanf("%d",&b[i]);

    printf("initial values of array b are:\n");

    for(i=0;i<5;i++)

      printf("%d ",b[i]);

    nzp(b,5);

    printf("\nlast values of array b are:\n");

    for(i=0;i<5;i++)

      printf("%d ",b[i]);

}

       iv.      在被调用函数中改变数组元素的值,则在调用函数中,数组的值也随之改变。

3.  局部变量和全局变量

1) 局部变量

         i.      局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的。

       ii.      形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。

      iii.      允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。如在前例中,形参和实参的变量名都为n,是完全允许的。

       iv.      在复合语句中也可定义变量,其作用域只在复合语句范围内。

2) 全局变量

全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。

例1:外部变量与局部变量同名。

int a=3,b=5;     /*a,b为外部变量*/

max(int a,int b) /*a,b为外部变量*/

{int c;

 c=a>b?a:b;

 return(c);

}

main()

{int a=8;

 printf("%d\n",max(a,b));

}

3) 静态局部变量

         i.      静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数调用结束后即释放。

       ii.      静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。

      iii.      如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。

例2:打印1到5的阶乘值。

int fac(int n)

{static int f=1;

 f=f*n;

 return(f);

}

main()

{int i;

 for(i=1;i<=5;i++)

 printf("%d!=%d\n",i,fac(i));

}

4) 用extern声明外部变量

外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。

例3:用extern声明外部变量,扩展程序文件中的作用域。

int max(int x,int y)

{int z;

 z=x>y?x:y;

 return(z);

}

main()

{extern A,B;

 printf("%d\n",max(A,B));

}

int A=13,B=-8;

说明:在本程序文件的最后1行定义了外部变量A,B,但由于外部变量定义的位置在函数main之后,因此本来在main函数中不能引用外部变量A,B。现在我们在main函数中用extern对A和B进行“外部变量声明”,就可以从“声明”处起,合法地使用该外部变量A和B。





C语言的42个运算符及15个优先级

一、赋值运算符
    赋值语句的作用是把某个常量或变量或表达式的值赋值给另一个变量。符号为‘=’。这里并不是等于的意思,只是赋值,等于用‘==’表示。
    注意:赋值语句左边的变量在程序的其他地方必须要声明。
    得已赋值的变量我们称为左值,因为它们出现在赋值语句的左边;产生值的表达式我们称为右值,因为她它们出现在赋值语句的右边。常数只能作为右值。
    例如:
        count=5;
        total1=total2=0;
    第一个赋值语句大家都能理解。   
    第二个赋值语句的意思是把0同时赋值给两个变量。这是因为赋值语句是从右向左运算的,也就是说从右端开始计算。这样它先total2=0;然后total1=total2;那么我们这样行不行呢?
        (total1=total2)=0;
    这样是不可以的,因为先要算括号里面的,这时total1=total2是一个表达式,而赋值语句的左边是不允许表达式存在的。
二、算术运算符
    在C语言中有两个单目和五个双目运算符。
       符号   功能
        +   单目正
        -   单目负
        *   乘法
        /   除法
        %   取模
        +   加法
        -   减法
    下面是一些赋值语句的例子, 在赋值运算符右侧的表达式中就使用了上面的算术运算符:
        Area=Height*Width;
        num=num1+num2/num3-num4;
    运算符也有个运算顺序问题,先算乘除再算加减。单目正和单目负最先运算。
    取模运算符(%)用于计算两个整数相除所得的余数。例如:
        a=7%4;
    最终a的结果是3,因为7%4的余数是3。
    那么有人要问了,我要想求它们的商怎么办呢?
        b=7/4;
    这样b就是它们的商了,应该是1。
    也许有人就不明白了,7/4应该是1.75,怎么会是1呢?这里需要说明的是,当两个整数相除时,所得到的结果仍然是整数,没有小数部分。要想也得到小数部分,可以这样写7.0/4或者7/4.0,也即把其中一个数变为非整数。
    那么怎样由一个实数得到它的整数部分呢?这就需要用强制类型转换了。例如:
        a=(int) (7.0/4);
    因为7.0/4的值为1.75,如果在前面加上(int)就表示把结果强制转换成整型,这就得到了1。那么思考一下a=(float) (7/4);最终a的结果是多少?
    单目减运算符相当于取相反值,若是正值就变为负值,若是负数就变为正值。
    单目加运算符没有意义,纯粹是和单目减构成一对用的。
三、逻辑运算符
    逻辑运算符是根据表达式的值来返回真值或是假值。其实在C语言中没有所谓的真值和假值,只是认为非0为真值,0为假值。
       符号   功能
        &&    逻辑与
        ||    逻辑或
        !    逻辑非
    例如:
        5!3;
        0||-2&&5;
        !4;
当表达式进行&&运算时,只要有一个为假,总的表达式就为假,只有当所有都为真时,总的式子才为真。当表达式进行||运算时,只要有一个
为真,总的值就为真,只有当所有的都为假时,总的式子才为假。逻辑非(!)运算是把相应的变量数据转换为相应的真/假值。若原先为假,则逻辑非以后为真,
若原先为真,则逻辑非以后为假。
    还有一点很重要,当一个逻辑表达式的后一部分的取值不会影响整个表达式的值时,后一部分就不会进行运算了。例如:
        a=2,b=1;
        a||b-1;
    因为a=2,为真值,所以不管b-1是不是真值,总的表达式一定为真值,这时后面的表达式就不会再计算了。
四、关系运算符
    关系运算符是对两个表达式进行比较,返回一个真/假值。
       符号   功能
        >    大于
        =    大于等于
        >=   右移赋值
        &=    位逻辑与赋值
        |=    位逻辑或赋值
        ^=    位逻辑异或赋值
    上面的十个复合赋值运算符中,后面五个我们到以后位运算时再说明。   
那么看了上面的复合赋值运算符,有人就会问,到底Total=Total+3;与Total+=3;有没有区别?答案是有的,对于A=A+1,表达式A被
计算了两次,对于复合运算符A+=1,表达式A仅计算了一次。一般的来说,这种区别对于程序的运行没有多大影响,但是当表达式作为函数的返回值时,函数就
被调用了两次(以后再说明),而且如果使用普通的赋值运算符,也会加大程序的开销,使效率降低。
七、条件运算符
    条件运算符(?:)是C语言中唯一的一个三目运算符,它是对第一个表达式作真/假检测,然后根据结果返回两外两个表达式中的一个。
        ?:
    在运算中,首先对第一个表达式进行检验,如果为真,则返回表达式2的值;如果为假,则返回表达式3的值。
    例如:
        a=(b>0)?b:-b;
    当b>0时,a=b;当b不大于0时,a=-b;这就是条件表达式。其实上面的意思就是把b的绝对值赋值给a。
八、逗号运算符
    在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
       假设b=2,c=7,d=5,
           a1=(++b,c--,d+3);
           a2=++b,c--,d+3;
对于第一行代码,有三个表达式,用逗号分开,所以最终的值应该是最后一个表达式的值,也就是d+3,为8,所以a=8。对于第二行代码,那么也是有三个表
达式,这时的三个表达式为a2=++b、c--、d+3,(这是因为赋值运算符比逗号运算符优先级高)所以最终表达式的值虽然也为8,但a2=3。
   还有其他的如位逻辑运算符,位移运算符等等,我们等到讲位运算时再说明。
九、优先级和结合性   
    从上面的逗号运算符那个例子可以看出,这些运算符计算时都有一定的顺序,就好象先要算乘除后算加减一样。优先级和结合性是运算符两个重要的特性,结合性又称为计算顺序,它决定组成表达式的各个部分是否参与计算以及什么时候计算。
    下面是C语言中所使用的运算符的优先级和结合性:
     优先级         运算符                结合性
     (最高)        () [] -> .            自左向右
             ! ~ ++ -- + - * & sizeof    自右向左
                    * / %                自左向右
                     + -                 自左向右
                    >                自左向右
                   >=              自左向右
                    == !=                自左向右
                     &                   自左向右
                     ^                   自左向右
                     |                   自左向右
                     &&                  自左向右
                     ||                  自左向右
                     ?:                  自右向左
       = += -= *= /= %= &= ^= |= >= 自右向左
     (最低)          ,                   自左向右

相关推荐