C笔记05-选择顺序结构,关系与相等,优先级和结合性
文章目录
- 选择控制结构与if语句
- 补充 : C语言_Bool关键字及与布尔类型相关的类型转换
- 关系运算符(relational operator)
- switch开关语句
- 浮点数的相等比较
- == 对浮点数"貌似"失效的原因
- 浮点数相等比较的解决办法
- 逻辑运算符与逻辑表达式
- C语言所有运算符优先级与结合性
- 基于C语言特性,我们应该养成哪些好的编程习惯来避免失误
所学视频及PPT截图来源: 爱课程资源共享课
选择控制结构与if语句
1.编程人员的基本素养: 全面,缜密
2.程序的组成: 数据,数据存储,算法
3.算法的描述: (flow-chart:流程图)
4.顺序结构
5.算法应该满足的条件:
6.if选择语句:
[表达式非0为真,0为假] (同样适用于while,for等语句)
无论if里的语句有多少,都应该使用大括号的原因:
(1)避免在程序维护时,需要向if中添加新语句时忘记打上花括号的情况
(2)用于严格限制if-else对齐,以免混淆出错:
7.条件运算符(C唯一的三目运算符)
条件运算符结合性: 从右到左
(多个条件运算符并列,先满足最右边的条件运算符的组成需要,然后再从右到左依次满足)
举例:
res = a>b?c:d<=e?e+10:sizeof(f)>4?10:g;
等同于:
res = (((a>b)? c:d<=e)? e+10:sizeof(f)>4)? 10:g;
补充 : C语言_Bool关键字及与布尔类型相关的类型转换
1._Bool关键字:
- C语言使用 _Bool 来定义布尔型变量。
- _ Bool类型长度为1(sizeof),取值范围为0或1。
- 将任意非零值赋值给 _ Bool 类型,都会先转换为1,表示真 ; 将零值赋值给 _ Bool类型,结果为0,表示假。
2.头文件stdbool.h:
头文件源代码主要内容:
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
也就是说,引入了stdbool.h之后,我们可以用bool代替_Bool,用true/false代替1/0.更符合其他大多数编程语言的习惯.
//测试:布尔类型的内存大小和赋值
_Bool a = 3;
_Bool b = 0;
printf("sizeof _Bool a : %d\nvalue of _Bool a : %d\n",sizeof(a),a);
printf("sizeof _Bool b : %d\nvalue of_Bool b : %d\n",sizeof(b),b);
// 打印:
// sizeof _Bool a : 1
// value of _Bool a : 1
// sizeof _Bool b : 1
// value of _Bool b : 0
关系运算符(relational operator)
注:笔者渣翻,原文请见 WG14 N1570
6.5 关系运算符(>,>=,<,<=)
约束条件:
2.必须满足下列情况之一:
(1)两操作数都是实数类型
(2)两操作数都是指向合格或不合格兼容对象类型的指针
语义:
3.如果操作数都是算数类型,就会执行常规数值转换(usual arithmetic conversion)
4.为了尽可能地实现关系运算符,一个指向非数组元素的指针和一个指向单元素数组中唯一元素并且以该元素的类型为数组类型的指针是等价的.
5.当两个指针相比较时, 其结果取决于两指针所指向的目标在地址空间的相对位置(而非目标所存储的值).
- 如果两个指针都同时指向同一个目标,或者都同时指向某一数组末尾元素之后的一个位置,这两个指针比较相等.
- 如果被指针指向的目标是同一个聚合类型(数组/结构类型),结构中后声明的成员的指针比先声明的成员的指针大;且在指向数组元素的指针中,目标元素下标较大的指针大于目标元素下标较小的指针.
- 指向同一联合类型的指针一律相等.
- 如果语句P指向某数组的一个元素且语句Q指向同一数组的最后一个元素,那么语句Q+1比P的值大.
- 在上述之外的任何情况下,两指针的大小比较都是未定义的.
6.关系运算符(>,>=,<,<=)所进行的比较结果为真,整个比较语句返回1;结果为假,返回0.返回类型为int类型.
switch开关语句
1.要点:
(1)判断表达式为int/char类型,不接受其他类型
(2)case与其后紧跟的值间有一个空格
(3)case后的值必须为常量,不可以是表达式
2.注意事项:
(1)default分支禁止省略
(2)如果case对应语句不用break语句结束,会发生case穿透,程序继续执行下一条case语句,直到遇到break语句或者整个代码块结束
(3)有时候,我们可以利用case穿透优化我们的代码; 其他情况下,每个case之后,必须用break语句结束.
//测试1:case穿透的利用--计算器程序(*,x,X统一判断为乘法运算符的实现)
switch(operator){
case '+': //此处实现加法运算;break;
case '-': //此处实现减法运算break;
case '*':
case 'x':
case 'X': //此处实现乘法的计算break;
case '/': //此处实现除法运算break;
default: //例外情况break;} //测试02:开关语句case穿透与语句顺序
int a = 10;
double b = 1.32;
_Bool c = 0;//test01:无case穿透下的default语句顺序的影响
switch(sizeof(c)){
case 4 : printf("it's an int\n");break;
case 8 : printf("it's a double\n");break;
default:printf("nothing here\n");break;
case 1 : printf("it's a _Bool\n");break;
}
// print:
// it's a _Bool
// conclusion:
// 无case穿透,default的位置顺序无影响//test02:有case穿透时default语句的顺序的影响
switch(sizeof(b)){
case 4 : printf("it's an int\n");break;
case 8 : printf("it's a double\n");
default:printf("nothing here\n");break;
case 1 : printf("it's a _Bool\n");break;
}
// print:
// it's a double
// nothing here
// conclusion:有case穿透时,default的位置顺序有影响
浮点数的相等比较
== 对浮点数"貌似"失效的原因
//测试:浮点数的大小比较
float f1 = 0.1;
double f2 = 0.1;
printf("%f\n",f1);
printf("%f\n",f2);if(f1-f2){printf("f1 不等于 f2\n");
}else{printf("f1 等于 f2\n");
}if(f1==f2){printf("f1 等于 f2\n");
}else{printf("f1 不等于 f2\n");
}
运行结果:
0.100000
0.100000
f1 不等于 f2
f1 不等于 f2
原因:
我们知道,C语言的浮点数是采用"阶码+尾数"形式存储的,而目前已知的所有的C/C++编译器都是按照IEEE(国际电子电器工程师协会)制定的IEEE 浮点数表示法来进行运算的。这种结构是一种科学表示法,用符号(正或负)、指数和尾数来表示,底数被确定为2,也就是说是把一个浮点数表示为尾数乘以2的指数次方再加上符号.
也就说,我们需要把要存储的数按照如下形式表示: (X为要表示的小数,An为系数且取值仅为0或1)
X = An×2n + An-1×2n-1 + …+ A1×21 + A0×20 + A-1×2-1 + A-2×2-2 + …+ A-(n-1)×2-(n-1) + A-n×2-n
上面的式子,当 系数下标 >= 0 时,为X的整数部分;当 系数下标 < 0 时,为X的小数部分.问题就出在小数部分.
- 无论整数部分为何值,总能用有限的位数将它表示并存储下来
- 小数部分则不同: 举例如下
0.5(10) = 0.1(2)
0.1(10) = 0.00011001100110011001100110011001100…(2),其系数是1100的循环.
当系数为无限数或循环时,我们为了存储,必须忍痛割爱,只截取有限的位数.而因为float类型和double类型的内存大小不同,截取的位数肯定不同(flaot较短而double较多).
而当我们用0.1对float和double赋值,然后两者进行计算和比较时,两者由于截取的位数不同,数值就不同,才有了上面代码的运行结果.
举例:(假设float截取8位,而double截取16位.注意!是假设)
0.1(10) = 0.00011001100110011001100110011001100…(2)
f1 = 0.00011001(2)
f2 = 0.0001100110011001(2)
当执行f1-f2或者f1==f2时,由于隐式转换:
f1’ = 0.0001100100000000(2)
f2 = 0.0001100110011001(2)
f1’的后8位都是0,当然和f2不相等了.
浮点数相等比较的解决办法
逻辑运算符与逻辑表达式
1.逻辑运算符(&&,||,!)
2.逻辑运算符的短路特性
3.逻辑运算符应用举例
C语言所有运算符优先级与结合性
1.C语言运算符优先级与结合性表
2.分析与简记
(1) 优先级
最高优先级的是选择数组元素,选择成员和括号(调整优先级/执行函数)的运算符,我们不妨将之归类为"选择运算符",由**[],(), . ,->**组成.
我们还可以用一张图片来描述:
没错,就是一辆"坦克",炮管尾部的一坨就是点号.
- 优先级排序: 选择 > (单目 > 双目 > 三目) > 赋值 > 逗号
- 选择运算符: 用于找到操作数
- 单双三目运算符: 利用操作数进行各种运算
- 赋值运算符: 将运算的结果保存起来
- 并且 单目和三目,赋值和逗号 以及我们的"选择运算符"都是各自出于同一优先级,而双目运算符一类横跨了多个优先级,需要单独拿出来分析:
- 双目运算符中,各个小类的优先级: 乘性(乘除余) > 加性(加减) > 移位(左右) > 关系 > 相等 > 位操作 > 逻辑操作
- 其中,位操作和逻辑操作,每一个运算符都独享一个优先级,顺序为:
- 位操作: 与&& > 或|| (注意: 非!是单目运算符,所以优先级高得多,不在此列)
- 逻辑操作: 与& > 异或^ (注意: 位取反~是单目运算符,所以优先级高得多,不在此列)
(2)结合性:
- 单目,三目,赋值为从右到左;其余为从左到右
- 什么是结合性?
(从左向右/左结合)当同优先级的运算符并列出现时,最先满足最左边运算符的构成需要,来进行分组,然后对剩余部分重复前面的步骤,从左至右依次满足.
基于C语言特性,我们应该养成哪些好的编程习惯来避免失误
- 不要想当然,使用数据类型时,先sizeof确定类型的大小,尽量避免使用int和long double类型
- if的判断式虽然不局限于关系和相等表达式,但我们应该一律化为 关系表达式.
- if的判断式使用相等表达式时,常量在左,变量在右.
- if中的语句,禁止省略大括号
- switch语句,不利用case穿透时,一律禁止省略结尾的break
- switch语句,一律禁止省略default分支
- 不要把自增,自减运算放到复杂的表达式中
C笔记05-选择顺序结构,关系与相等,优先级和结合性相关推荐
- python笔记05: 程序结构
程序结构 三大结构 顺序 分支 循环 分支 单路分支 分支的基本语法 if 条件表达式:语句1语句2语句3...... 条件表达式就是计算结果必须为布尔值的表达式 表达式后面的冒号不能少 注意if后面 ...
- Java三大结构 顺序结构、选择结构、循环结构
文章目录 顺序结构 选择结构 if单选结构 if双选结构 if多选结构 嵌套的if结构 switch多选择结构 if.while语句的选择与区别 循环结构 while循环 do...while循环 f ...
- Java02-day02【运算符(赋值、关系、逻辑、三元、算数、自增自减)、分支语句(顺序结构、if语句)】
java零基础入门到精通(2019版)[黑马程序员] 视频+资料:[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg 提取码:zjxs] &qu ...
- 非顺序控制结构的c语言语法是怎样的,流程控制语句:顺序结构和选择结构
流程控制语句 概述:控制程序的执行流程 分类: 顺序结构 选择结构 循环结构 顺序结构语句 顺序结构语句:从上往下,依次执行 选择结构 if语句: switch语句: if语句: 格式1: 格式2: ...
- Python中的程序控制结构 顺序结构和选择结构
目录 Python中的程序控制结构(一) 1.程序中的组织结构 2.顺序结构 3.对象的布尔值 4.分支结构 4.1 单分支if结构 4.2 双分支if...else结构 4.3 多分支if...el ...
- day20.顺序结构 选择结构
顺序结构,选择结构 昨天的scanner都会了吧,那今天就来看看顺序结构和选择结构 顺序结构 java的基本结构就是顺序结构,除非特别指明,否则就按照顺序结构一句一句执行 顺序结构是最简单的算法结构 ...
- 04_星仔带你学Java之流程语句(顺序结构、选择结构、循环结构、控制循环结构语句)
大家好,我是星仔.本博客收录于华星详谈-学习中心.本学习中心收集了Java整个技术体系的所有技术要点.每篇博客后面或者知识点结尾都附带有面试题,提供给大家巩固本章内容. 为各位同胞们能 ...
- 【Java】流程控制 - 顺序结构、 选择(分支)结构(单分支、双分支、多分支、嵌套)、循环结构(for、while、do...while)、跳转语句(break、continue)
流程控制语句结构 文章目录 流程控制语句结构 一. 顺序结构 1. 输出语句 2. 输入语句 3.code 二.复合语句 三. 分支结构 1. 条件判断 1.单分支结构 2.双分支结构 3.多分支结构 ...
- MATLAB顺序结构及选择结构程序设计
一.实验目的 (1)掌握建立和执行M文件的方法 (2)掌握输入输出的方法 (3)掌握顺序结构程序设计方法 (4)掌握利用if以及switch语句实现多分支选择结构的方法 二.实验原理与实验设备 原理: ...
- python入门之控制结构顺序与选择结构_Python 入门之控制结构 - 顺序与选择结构——第1关:顺序结构...
Python 入门之控制结构 - 顺序与选择结构--第1关:顺序结构 任务描述 程序最基本的结构就是顺序结构,顺序结构就是程序按照语句顺序,从上到下依次执行各条语句. 本关要求学习者理解顺序结构,并对 ...
最新文章
- 温度自动调节 c语言编写,室内温度自动调节控制系统课程设计(26页)-原创力文档...
- ITK:将具有RGB像素的vtkImageData转换为itk :: Image
- 在Spring Boot测试中使用Testcontainer进行数据库集成测试
- jvm默认的初始化参数_您是否应该信任JVM中的默认设置?
- c语言程序求一一组数平均值,编写求一组整数的和与平均值的程序
- 过度扩容 A股“虚胖”
- 睡眠周期时长测试软件,“智能时钟”测睡眠周期 最佳时候叫醒你
- html中th 与thead tbody的 使用
- IE6不支持min-heigt的bug解决的办法
- 借助URLOS快速安装织梦cms
- NLP之路-Dataset大全
- 济南学习 Day 5 T2 am
- WEB 开发异常:java.lang.ClassNotFoundException
- excel服务器2010网站,勤哲Excel服务器2010企业版(完整安装包)
- php ip纯真数据库Dat,php读取纯真ip数据库使用示例
- 利用原生JS将下载链接转换为二维码
- win10添加开机启动项_Win10+Deepin双系统开启启动项调整
- Variable used in lambda expression should be final or effectively final 问题的解决和追根溯源
- 体系结构实验(2)—— 不同指令集的对比
- 幼儿园计算机教师论文,幼儿园计算机辅助教学中教师角色定位研究