title: 第五章 运算符、表达式和语句
author: HardyDragon
tags: C Notes


第五章 运算符、表达式和语句

5.1 循环简介

5.2 基本运算符

5.2.1 赋值运算符:=

±*/

运算符优先级

优先级和求值顺序

5.3 其他运算符

5.3.1 sizeof 运算符和size_t类型

5.3.2 求模运算符:%

5.3.3 递增运算符:++ 递减运算符:–

优先级

不要自作聪明

5.4 表达式和语句

5.4.1 表达式

5.4.2 语句

5.4.3 复合语句(块)

5.5 类型转换

5.6 带参数的函数

5.7 示例程序

5.8 关键概念

5.9 本章小结

5.10 复习题

5.11 编程练习


5.1 循环简介

循环可以重复执行行为,让程序更有趣,更强大,更哲学,更 ♂(doge);

// shoes1.c -- 将鞋码转换成英寸
#include<stdio.h>
#define ADJUST 7.31
int main(int argc, char const *argv[])
{const double SCALE = 0.333; // const 变量double shoe ,foot;shoe = 9.0;foot = SCALE * shoe + ADJUST;printf("Shoe size (men's) foot length\n");printf("%10.1f %15.2f incher\n",shoe,foot);return 0;
}

result

Shoe size (men's) foot length9.0           10.31 incher

应用while循环 输出不同鞋码的脚长

// shoes2.c -- 计算多个不同鞋码对应的脚长
#include <stdio.h>
#define ADJUST 7.31
int main(int argc, char const *argv[])
{const double SCALE = 0.333;double shoe, foot;printf("Shoe size (men's)   foot length\n");shoe = 3.0;while (shoe < 18.5){foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n",shoe,foot);shoe = shoe + 1.0;}printf("If the shoe fits,wear it.\n");return 0;
}

result:

Shoe size (men's)   foot length3.0            8.31 inches4.0            8.64 inches5.0            8.97 inches6.0            9.31 inches7.0            9.64 inches8.0            9.97 inches9.0           10.31 inches10.0           10.64 inches11.0           10.97 inches12.0           11.31 inches13.0           11.64 inches14.0           11.97 inches15.0           12.31 inches16.0           12.64 inches17.0           12.97 inches18.0           13.30 inches
If the shoe fits,wear it.

关于while 循环的原理,当程序第一次到达while循环时,会检查圆括号中的条件是否为真。

while语句下面的花括号内容就是要被重复执行的内容,花括号以及被花括号括起来的部分被称为

5.2 基本运算符

pow(3.5,2.2); 返回3.5的2.2次幂

= 的左侧必须是一个变量名,实际上赋值运算符左侧必须引用一个存储位置。最简单的就是变量名,当然指针也可用于指向一个存储位置。
赋值表达式语句的目的是为了将值存储到内存位置上。用于存储值的数据区域统称为数据对象。使用变量名是标识对象的一种方法。还可以指定数组的元素、结构的成员,指针表达式为对象。
左值是C语言的术语,用于标识对象的名称或表达式。因此,对象指的是实际的数据存储,而左值用于标识或定位存储位置的标签。
对于早期的C而言,提到左值意味着:

  1. 它指定一个对象,所以引用内存的地址;
  2. 它可以在赋值运算符的左侧,左值中的1源自left。

但是由于const的出现导致第二条有时不符合了。便改为了可修改的左值 用于 标识可修改的对象。
右值指的是能赋值给可修改左值的量,且本身不是左值。

// golf.c -- 高尔夫锦标赛积分卡
#include<stdio.h>
int main(int argc, char const *argv[])
{int jane,tarzan,cheeta;cheeta = tarzan = jane = 68;printf("                    cheeta  tarzan  jane\n");printf("First round score %4d %8d %8d\n",cheeta,tarzan,jane);return 0;
}

result:

                    cheeta  tarzan  jane
First round score   68       68       68

C语言的三重赋值是可以的,且赋值顺序是从右往左,首先把86赋值给jane,然后再赋给tarzen,最后赋给cheeta。
C99新加的一元+运算符:

dozen = +12;

以前是不被允许的。

打印1-20的平方:

// squares.c-- 计算1-20的平方
#include <stdio.h>
int main(int argc, char const *argv[])
{int num = 1;while (num < 21){/* code */printf("%4d %6d\n", num, num * num);num += 1;}return 0;
}

result:

   1      12      43      94     165     256     367     498     649     8110    10011    12112    14413    16914    19615    22516    25617    28918    32419    36120    400

除法运算符: /
整数除法的结果是整数,浮点数除法的结果是浮点数。整数除法结果的小数部分被截断

// divide.c -- 演示除法
#include <stdio.h>
int main(int argc, char const *argv[])
{printf("5/4 = %d \n", 5 / 4);printf("6/3 = %d \n", 6 / 3);printf("7/4 = %d \n", 7 / 4);printf("7./4 = %1.2f \n", 7. / 4);printf("7./4 = %1.2f \n", 7. / 4);return 0;
}

result:

5/4 = 1
6/3 = 2
7/4 = 1
7./4 = 1.75
7./4 = 1.75

混合整数和浮点数计算的结果是浮点数,计算机不能真正的用浮点数除以整数,编译器会把两个运算对象转换成相同的类型。在除法运算前,整数会被转换为浮点数。
C99规定整数除法的结果不对小数部分四舍五入,直接截断小数部分。
运算优先级:先乘除,后加减,括号强
5.3 其他运算符

  • sizeof 运算符 和 size_t 类型

    sizeof 运算符 以字节为单位返回运算对象的大小,建议对变量和类型都用括号。

    sizeof 返回的是 size_t 类型的值,是一个无符号的整数类型,C语言将size_t 作为 unsigned int或unsigned long 的别名,可以使用typedef 实现。
    C99 新加了 %zd 转换说明用于printf() 显示size_t 类型的值。如果不支持%zd ,可使用 %u 或 %lu 来替代。

  • 求模运算符:%(对整数的求余数)

    // min_sec.c -- 把秒数转换为分和秒
    #include <stdio.h>
    #define SEC_PER_MIN 60
    int main(int argc, char const *argv[])
    {int sec, min, left;printf("enter seconds:\n");scanf("%d", &sec);while (sec > 0){/* code */min = sec / SEC_PER_MIN;  // 截断分钟left = sec % SEC_PER_MIN; // 剩下的秒数printf("%d seconds is %d minutes,%d seconds.\n", sec,min, left);printf("enter seconds:\n");scanf("%d", &sec);}printf("Done!");return 0;
    }

    result:

    enter seconds:
    154
    154 seconds is 2 minutes,34 seconds.
    enter seconds:
    567
    567 seconds is 9 minutes,27 seconds.
    enter seconds:
    0
    Done!
    

    如果不支持C99的标准,可以对a和b两个整数使用 a - (a/b) *b 来计算a%b 的值。

  • 递增运算符:++/递减运算符:–

    注意++/–的位置,放在对象前面就是先加后执行语句,放在对象后面就是先执行后加值。对于递减也是如此。

    // add_one.c -- 递增:前缀和后缀
    #include <stdio.h>
    int main(int argc, char const *argv[])
    {int ultra = 0, super = 0;while (super < 5){/* code */super++;++ultra;printf("super = %d ,ultra = %d \n", super, ultra);}return 0;
    }

    result:

    super = 1 ,ultra = 1
    super = 2 ,ultra = 2
    super = 3 ,ultra = 3
    super = 4 ,ultra = 4
    super = 5 ,ultra = 5
    

    递增递减运算符让程序更简洁,提高可读性。例如:

    shoe = 3.0;
    while (shoe < 18.5)
    {foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n",shoe,foot);shoe = shoe + 1.0;
    }
    

    可以修改成这样

    shoe = 2.0;
    while (++shoe < 18.5)
    {foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n",shoe,foot);
    }
    

    在上面的代码中,将变量的递增过程放入while循环的条件中,这种结构在C语言中很貌似很普遍。

    注意变量赋值时候使用要注意其值的变化。

    // post_pre.c -- 前缀和后缀
    #include <stdio.h>
    int main(int argc, char const *argv[])
    {int a = 1, b = 1;int a_post, pre_b;a_post = a++; //后缀递增pre_b = ++b;  // 前缀递增printf("a a_post b pre_b \n");printf("%ld %5d %5d %5d\n", a, a_post, b, pre_b);return 0;
    }

    result:

    a a_post b pre_b
    2     1     2     2
    

    a和b递增了1,但是a_post 是a递增前的值,而 b_pre 是b 递增之后的值。

    如果使用前缀或后缀会对代码产生不好的影响,就不要使用,例如:

    b = ++i;
    

    应该替换成

    ++i;
    b = i; // 如果第一行使用 i++ 也不影响b的值
    
  • 关于递增递减运算符的优先级

    只有圆括号的优先级高于它们。例如:x*y++ 表示 的是 (x) * (y++) 。

  • 不要自作聪明

    编译器可以自行选择先对那个函数中的参数求值,或许可以提高效率,但是如果参数使用了递增运算符就会遇到一些问题。编译器可能会先计算递增的变量就导致输出结果异常。So,应当遵循以下规则来避免出现类似问题,以及正确规范的使用递增递减运算符,提高程序的可读性。

    • 如果一个变量出现在一个函数的多个参数中,不要对该变量使用递增或递减运算符;
    • 如果一个变量多次出现在一个表达式中,不要对该变量使用递增递减运算符

5.4 表达式和语句

  • 表达式

    表达式由运算符和运算对象组成,每个表达式都有一个值。

  • 语句

    一条语句相当于一条完整的计算机指令,大部分语句以分号;结尾。最简单的语句是空语句

    C把表达式加上一个分号的表达式都看作是一条语句,例如:

    8;
    3 + 4;
    
    // addemup.c -- 几种常见的语句
    #include<stdio.h>
    int main(int argc, char const *argv[])
    {int count=0,sum=0;  // 声明while (count++<20)  // 迭代语句{/* code */sum += count;}printf("sum = %d\n",sum);return 0;   // 跳转语句
    }
  • 副作用和序列点

    副作用是对数据对象或文件的修改。例如:printf() 的返回值是待显示字符的个数,这个就是副作用。

    序列点是程序执行的点,在这个点上,所有的副作用都在进入下一步前发生。C语言中的分号标记了一个序列点,意思是,赋值运算符、递增/递减运算符对运算对象的改变必须要在程序执行下一条语句前完成。任何一个完整表达式的结束也是一个序列点。例如while语句中的条件表达式就是完整的表达式,这个就是一个序列点,要在下一条程序执行前先作用完成。例如:

    #include <stdio.h>
    #include<limits.h>
    #include<string.h>
    int main()
    {int y,x;x = 0;y = (4 + x++) + (6 + x++);printf("y = %d\n",y);return 0;
    }

    result:

    y = 11
    

    应该避免编写这样的语句,因为 (4 + x++) 并不是一个完整的表达式,所以C无法保证在 (4 + x++) 求值后立即递增x,所以结果会有所不同。

     y = (4 + x++) + (6 + x++);
    

    5.5 类型转换

    在特定情况一些类型会自动被转换升级/降级。

    • 强制转换

      应该避免自动类型转换,使用强制类型转换,稳。

      #include <stdio.h>
      int main()
      {int mice;mice = (int)1.6 + (int)1.7;printf("mice = %d\n",mice);// printf("%2.2e",1201.0);return 0;
      }

      result:

      mice = 2
      

5.6 带参数的函数

// pound.c -- 定义一个带一个参数的函数
#include<stdio.h>
void pound(int n); // ANSI函数原型声明
int main(int argc, char const *argv[])
{int times = 5;char ch = '!';  // ANSI码 33float f = 6.0f;pound(times);   // int pound(ch);      // pound((int)ch); pound(f);       // pound((int)f); return 0;
}
void pound(int n){while (n-->0){/* code */printf("#");}printf("\n");}

result:

#####
#################################
######

函数若不接受任何参数,就应该在圆括号中写上关键字 void。声明参数称为形式参数(形参),传入的参数被称为实际参数(实参)。
遇到参数和函数的形参类型不匹配的情况,程序的函数原型就会自动将实参转换为对应的类型以满足函数的要求。应当避免这种不正常的情况,因为遇到了参数太大,超过了int的取值范围就会拉闸。

5.7 示例程序

5.8 关键概念

5.9 本章小结

只需要一个运算对象的运算符称为一元运算符,需要两个运算对象的运算符称为二元运算符。

5.10 复习题

第五章运算符表达式和语句相关推荐

  1. 《C Primer Plus》第五章-运算符 表达式和语句(笔记、复习题、编程题,副作用和序列点,升降级)

    文章目录 运算符 表达式和语句 本章内容 循环简介 基本运算符 赋值运算符:= 几个术语:数据对象.左值.右值和运算符 加法运算符:+ 减法运算符:- 5.2.4 符号运算符:-和+ 乘法运算符:* ...

  2. 【JAVA SE】第三章 运算符、条件语句、switch结构、while循环、do…while循环、for循环、break关键字以及break和continue关键字

    第三章 运算符.条件语句.switch结构.for循环.break关键字以及break和continue关键字 文章目录 第三章 运算符.条件语句.switch结构.for循环.break关键字以及b ...

  3. 《C Primer Plus》中文第六版 编程练习答案 第五章 运算符、表达式和语句

    C Primer Plus 第5章 运算符.表达式和语句 编程练习答案 ***先说一下关于 i++和 ++i 情况.*** 1.编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间.使用#de ...

  4. 第五章 运算符、表达式和语句

    程序清单5.1,shoes1.c: /* shoes1.c -- 把鞋码转换成英寸 */ #include <stdio.h>#define ADJUST 7.31 // 字符常量 int ...

  5. C Primer Plus编程题-第五章 运算符、表达式和语句

    第一题: 编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间.使用#define或const创建一个表示60的符号常量或const变量.通过while循环让用户重复输入值,直到用户输入小于或 ...

  6. C Primer Plus第六版第五章运算符,表达式,语句源码

    源码 //5.1#include<stdio.h> #define ADJUST 7.31 int main(void) {const double SCALE = 0.333;doubl ...

  7. 零基础学Python(第五章 运算符)

    本套学习内容共计[22]个章节,每个章节都会有对应的从0-1的学习过程详细讲解,希望可以给更多的人提供帮助. 开发环境:[Win10] 开发工具:[Visual Studio 2019] 1.什么是运 ...

  8. 《C Prime Plus》(第六版) 第05章 运算符、表达式和语句 例题集和编程练习

    OS: Mac Catalina 10.15.4 Hardware: Intel Core i9/16G 2667MHz DDR4 编译器版本:Mac Xcode 11.6  第05章 运算符.表达式 ...

  9. 《C Primer Plus(第6版)中文版》 第5章 运算符、表达式和语句 学习笔记

    对标题和序号稍加修改. 5.1 循环简介 本章仍从一个程序开始. #include<stdio.h> int main(void) {int val=1;while(val<11){ ...

最新文章

  1. Zuul(SpringCloud学习笔记一)
  2. 【PAT乙级】1086 就不告诉你 (15 分)
  3. Git 内部原理图解——对象、分支以及如何从零开始建仓库
  4. C语言试题三十五之找出一维整型数组元素中最大的值和它所在的下标,最大的值和它所在的下标通过形参传回。主函数中x是数组名,n 是x中的数据个数,max存放最大值,index存放最大值所在元素的下标。
  5. Java Jar包的压缩、解压使用指南
  6. 安卓逆向_19( 一 ) --- APK保护策略【APP打开就崩溃 之 霸哥apk过签名校验】
  7. qt使用自带的日志输出实例输出日志时,在日志中显示行数
  8. c语言读取nc文件格式,nc文件资料地读取与处理.doc
  9. ZetCode 杂项教程
  10. vue.js+webpack 为 img src 赋值的路径问题解决方法
  11. buildroot 文件系统添加telnet, ssh, 以及制作注意事项
  12. vue 同步加载_如何在vue里实现同步阻塞请求,请求完成之前不加载页面或组件?...
  13. iMac电脑启动ideal跑Java项目报错(Class JavaLaunchHelper is implemented in both...One of the two will be used.)
  14. SSM项目实战之十四:分页实现
  15. 自学编程到底有多难?
  16. 如何将本地代码保存至码云中
  17. Kali linux 基础常用指令详解
  18. 【VUE】前端搜索引擎优化seo
  19. java读取ppm图片,在Java中将PPM转换为JPG或BMP
  20. 华为Android彩蛋,华为手机DIY拨号及彩蛋功能介绍

热门文章

  1. 大数据初学必须掌握的技能
  2. 前端“智能”静态资源管理 - Onebox - 博客园
  3. Leetcode1278
  4. Java—二维码生成与识别(一)
  5. os什么意思python_Python中import os是什么意思?
  6. 如何为豆瓣FM写一个chrome的歌词插件
  7. 我的MSN机器人终于有了自己的头像
  8. 自定义gii生成模块
  9. 没有oracle客户端可以连接数据库,Oracle数据库之SqlDbx连接oracle(无需安装Oracle客户端)...
  10. CSS( Cascading Style Sheets )简书