【C primer plus】第五章 运算符、表达式和语句

5.1循环简介

  while循环原理:当程序到达while循环时,会检查圆括号中的条件是否为真,条件为真,程序进入块中继续执行,块中内容执行完,程序返回while入口部分检查条件。
代码使用一对花括号来标出while循环的范围,花括号之间的内容就是要被重复执行的内容,花括号以及被花括号括起来的部分被称为块。
当检查条件为假时控制转到紧跟while循环后面的第一条语句。

5.2 基本运算符

  5.2.1 赋值运算符:=

  在C语言中,=并不意味着相等,而是一个赋值运算符。
a=1;
  =号左侧是一个变量名,右侧是赋给该变量的值。符号=被称为赋值运算符。另外,上面的语句读作“把值1赋给变量a”。赋值行为从右往左进行。
i=i+1;
  该语句的意思是:找出变量i的值,把该值加1,然后把新值赋给变量i
  不能给常量赋值,常量本身就是它的值。因此,等号左侧的项必须是一个变量名。事实上,赋值运算符左侧必须引用一个存储位置,最简单的方法是使用变量名。C使用可修改的左值标记那些可赋值的实体。
  赋值表达式语句的目的是把值储存到内存位置上,用于储存值的数据存储区域统称为数据对象。使用变量名是表示对象的一种方法。
  左值用于标识特定数据对象的名称或表达式。因此,对象指的是实际的数据存储,而左值是用于标识或定位存储位置的标签。
  可修改的左值,用于标识可修改的对象。所以赋值运算符的左侧应该是可修改的左值。也可称为对象定位值。
  右值或表达式的值指的是能赋值给可修改左值的量,且本身不是左值。右值可以是常量、变量或其他可求值的表达式。
  被称为“项”的就是运算对象,即运算符操作的对象。

  5.2.2 加法运算符:+

  加法运算符用于加法运算,使其两侧的值相加。
  相加的运算对象可以是变量,也可以是常量

  5.2.3 减法运算符:-

  减法运算符用于减法运算,使其左侧的数减去右侧的数。
  +和-运算符都被称为二元运算符,即这些运算符需要两个运算对象才能完成操作。

  5.2.4 符号运算符:-和+

  减号还可用于标明或改变一个值的代数符号。
  以这种方式使用的负号被称为一元运算符,一元运算符只需要一个运算对象。
  一元+运算符,它不会改变运算对象的值或符号。

  5.2.5 乘法运算符:*

  符号*表示乘法

  5.2.6 除法运算符:/

  C使用符号/来表示除法。/左侧的值是被除数,右侧的值是除数。
  整数除法和浮点数出发不同。浮点数除法的结果是浮点数,而整数除法的结果是整数。整数除法结果的小数部分被丢弃,这一过程称为截断。
  负数的整数除法直接丢弃小数部分,这种方法被称为“趋零截断”。

  5.2.7 运算符优先级

  C语言通过运算符优先级来解决操作顺序的问题。每个运算符都有自己的优先级。乘除法的优先级比加减法高,所以先执行乘法和除法。如果两个运算符的优先级相同,他们处理同一个运算对象,则根据它们在语句中出现的顺序来执行。对大多数运算符而已,这种情况都是按从左到右的顺序进行(=运算符除外)。
  许多人喜欢用表达式树来表示求值的顺序
 

  最先执行圆括号中的部分。圆括号内部按正常的规则执行。

 

 

5.3 其他运算符

  5.3.1 sizeof运算符和size_t类型

  sizeof运算符以字节为单位返回运算对象的大小,1字节定义为char类型占用的空间大小。运算对象可以是具体的数据对象或类型,如果运算对象是类型则必须用圆括号将其括起来。
  C语言规定,sizeof返回size_t类型的值。size_t是unsigned int或unsigned long的别名。%zd转换说明用于printf()显示size_t类型的值。

  5.3.2 求模运算符

  求模运算符用于整数运算。求模运算符给出其左侧整数除以右侧整数的余数。求模运算符只能用于整数,不能用于浮点数。
  如果第一个运算对象是负数,那么求模的结果为负数,如果第一个运算对象是整数,那么求模的结果也是正数。

  5.3.3 递增运算符:++

  递增运算符执行简单的任务,将其运算对象递增1,该运算符以两种方式出现。第一种方式,++出现在其作用的变量前面,这是前缀模式,第二章方式,++出现在其作用的变量后面,这是后缀模式。两种模式的区别在于递增行为发生的时间不同。
1 int a=1, b=1, a_post, b_pre;
2 a_post = a++;    //后缀:使用a的值之后,递增a    a_post = 1;
3 b_pre = ++b;    //前缀:使用b的值之前,递增b    b_pre = 2;

  5.3.4 递减运算符:--

  每种形式的递增运算符都有一个递减运算符与之对应,用--代替++即可

  5.3.5 优先级

  递增和递减都有很高的结合优先级,只有圆括号的优先级比它们高。
  递增和递减只能影响一个可修改的左值。
  如果一个变量出现在一个函数的多个参数中,不要对该变量使用递增或递减运算符
  如果一个变量多次出现在一个表达式中,不要对该变量使用递增或递减运算符。

5.4 表达式和语句

  5.4.1 表达式

  表达式由运算符和运算对象组成。最简单的表达式是一个单独的运算对象,以此为基础可以建立复杂的表达式。
  运算对象可以是常量、变量和二者的组合,一些表达式由子表达式组成。
  每个表达式都有一个值

  5.4.2 语句

  语句是C程序的基本构建块。一条语句相当于一条完整的计算机指令。在C中大部分语句都以分号结尾。
  最简单的语句是空语句:
   1 ; //空语句 
  C把末尾加上一个分号的表达式都看做是一个语句。语句可以改变值或调用函数
  虽然一条有用的语句相当于一条完整的指令,但并不是所有的指令都是语句。
  C中的声明不是语句!!!
  赋值表达式语句在程序中很常用:它为变量分配一个值。赋值表达式语句的结构是,一个变量名,后面是一个赋值运算符,在跟着一个表达式,最后以分号结尾。
  函数表达式语句会引起函数调用。
  while循环中只有一条语句可以不需要用花括号括起来,多条语句需要用花括号括起来,这种语句是复合语句。
  while语句是一种迭代语句,有时也被称为结构化语句,因为他的结构比简单的赋值表达式语句复杂。
  副作用是对数据对象或文件的修改。语句的主要作用是对表达式求值。
  序列点是程序执行的点,在该点上,所有的副作用都在进入下一步之前发生。在C语言中语句的分号标记了一个序列点,意思是运算符对运算对象的改变必须在程序执行下一条语句之前完成。另外,任何一个完整表达式的结束也是一个序列点。
  完整表达式就是指这个表达式不是另一个更大表达式的子表达式,例如while循环中作为测试条件的表达式。

  5.4.3 复合语句(块)

  复合语句是用花括号括起来的一条或多条语句。复合语句也称为块。

5.5 类型转换

  通常,在语句和表达式中应适用类型相同的变量和常量,但是,如果使用混合类型,C采用一套规则进行自动类型转换。
  1.当类型转换出现在表达式时,无论是unsigned还是signed的char和short都会被自动转换成int,如果有必要会被转换成unsigned int。在K&C那时的C中,float会被自动转换成double,由于都是从较小类型转换为较大类型,所以这些转换被称为升级。
  2.涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别。
  3.类型的级别从高至低依次是long double,double,float,unsigned long long,long long,unsigned long,long,unsigned int,int,例外的情况,当long和int的大小相同时,unsigned int 比long的级别高,之所以short和char类型没有列出,是因为它们已经被升级到了int或unsigned int
  4.在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类型。这个过程可能导致类型升级或降级。所谓降级,是指把一种类型转换成更低级别的类型。
  5.当作为函数参数传递时,char和short被转换成int,float被转换成double。
  类型升级通常不会有问题,但是类型降级会导致麻烦,原因是较低类型可能装不下整个数字。
  如果待复制的值与目标类型不匹配时,规则如下:
  1.目标类型是一个有符号整形,且待赋的值是整数,结果因实现而异。
  2.目标类型是无符号整型,且待赋的值是整数时,额外的位被忽略。
  3.如果目标类型是一个整形,且待赋的值是浮点数,该行为是未定义的。
  如果把一个浮点值转换成整数类型,浮点类型被降级为整数类型时,原来的浮点值会被截断。
  5.5.1 强制类型转换运算符
  强制类型转换符,即在某个量的前面放置用圆括号括起来的类型名,该类型名即是希望转换成的目标类型。圆括号和它括起来的类型名构成了强制类型转换运算符。其通用形式是:
  (type)
  用实际需要的类型替换type即可。

5.6 带参数的函数

 1 //pound.c -- 定义一个带一个参数的函数
 2 #define _CRT_SECURE_NO_WARNINGS
 3 #include <stdio.h>
 4 void pound(int n);
 5 int main(void)
 6 {
 7         int times = 5;
 8         char ch = '!';        //ASCII码是33
 9         float f = 6.0f;
10         pound(times);        //int 类型的参数
11         pound(ch);            //和pound((int)ch)相同
12         pound(f);            //和pound((int)f)相同
13 
14         return 0;
15 }
16 
17 void pound(int n)            //ASCII风格函数头
18 {                    //表明该函数接受一个int类型的参数
19         while (n-- > 0)
20             printf("#");
21         printf("\n");
22 }
  首先看程序的函数头:
void pound(int n)
  如果函数不接受任何参数,函数头的圆括号中应该写上关键字void,由于该函数接受一个int类型的参数,所以圆括号中包含一个int类型变量n的声明,参数名应遵循C语言的命名规则。
  声明参数就创建了被称为形式参数(简称形参)的变量。该例中,形式参数是int类型的变量n,像pound(10)这样的调用函数会把10赋给n。我们称函数调用传递的值为实际参数,简称实参。所以,函数调用pound(10)把实际参数10传递给函数,然后该函数把10赋给形式参数。。
  形参是变量,实参是函数调用提供的值,实参被赋给相应的形参。
  变量名是函数私有的,即在函数中定义的函数名不会和别处的相同名称发生冲突。也就是说,程序中出现了两个同名的变量,但是程序可以区分它们。
  程序开头的函数原型即是函数的声明,描述了函数的返回值和参数。
posted @ 2023-06-23 17:14  永生辉皇  阅读(99)  评论(0)    收藏  举报