C语言KR圣经笔记 2.11条件表达式 2.12优先级和求值顺序

news2024/11/17 0:06:41

2.11条件表达式

 if (a > b) 
     z = a; 
 else 
     z = b; 

上面的语句计算 a 和 b 中的最大值并存入 z。而使用三元操作符 ? :  条件表达式,为这个结构及类似结构提供了另一种写法。在如下表达式

expr1 ? expr2 : expr3

中,首先对 expr1 求值。如果值非0 (为真),则对 expr2 求值,而得到的也是整个条件表达式的值。若 exp1 的值为0(为假),则对 expr3 求值,得到整个表达式的值。 expr2 和 expr3 中只会有一个表达式被求值。因此,把 z 设为 a 和 b 的最大值就能写成:

z = a > b ? a : b;    /* z = max(a,b) */

需要注意,条件表达式确实是一个表达式,它能出现在任何其他表达式可以出现的地方。如果 expr2 和 expr3 的类型不同,则结果的类型取决于本章前面讨论过的转换规则。例如, 如果 f 是 float 而 n 是 int,则表达式

(n > 0) ? f : n

的类型是 float, 不管 n 是否大于 0。

条件表达式的第一个表达式两边不用加上括号,因为 ?: 的优先级非常低,仅高于赋值。然而加上括号是明智的,因为这会让条件表达式的条件部分看起来更明显。

条件表达式可以带来更简洁的代码。例如,下面这个循环会打印数组的 n 个元素,每行10个,中间用空格隔开,每行(包括最后一行)末尾以换行符结束。

for (i = 0; i < n; ++i)
    printf("%6d%c", a[i], (i%10==9 || i== n-1) ? '\n' : ' ');

每10个元素后面打印一个换行符,第n个元素后面也要。其他所有元素后面打印空格。代码可能看起来有点绕,但比对应的 if-else 写法要紧凑。还有个不错的例子是

printf("You have %d items%s.\n", n, n==1 ? "" : "s"); 

练习2-10、重写 把大写字母转小写的 lower 函数,用条件表达式,不用 if-else。

2.12优先级和求值顺序

表2-1总结了所有操作符的优先级和结合性,包括那些我们还没讲到的。同一行的操作符有相同的优先级;行按优先级降序排列,例如 操作符 * / % 的优先级相同,而它们三个的优先级都比二元操作符 + -  要高。括号“操作符” ( ) 指的是函数调用。操作符 -> 和 . 用来访问结构的成员,还有 sizeof(对象的大小),都会在第6章讲到。第5章会讨论  * (通过指针引用)和 & (对象的地址),而第3章会讨论逗号操作符。

注意位操作符 & ^ | 优先级低于 == 和 !=。这隐含说明,用来测试位的表达式如

if ((x & MASK) == 0) ...

里面必须全部用括号包起来,才能得到想要的结果。

C,和大多数语言一样,并没有指定一个操作符中多个操作数的求值顺序。(操作符  && || ?: 和逗号操作符除外)。例如语句

x = f() + g()

f 可能 在 g 之前求值,可能相反;这样如果 f 或 g 改变了对方依赖的一个变量值,则 x 的值依赖于求值顺序。应对这种情况,可以用临时变量来保存中间结果,以保证所需的顺序。

类似的,函数的多个参数的求值顺序也是没有规定的,因此语句

printf("%d %d\n", ++n, power(2,n));    /* WRONG */

用不同的编译器可以产生不同的结果,依赖于 n 是否在 power 被调用之前自增。当然,解决方法是写成

++n;
printf("%d %d\n", n, power(2,n));

函数调用,嵌套的赋值语句,以及自增和自减操作符,都会带来“副作用”——作为表达式求值的副产品,某些变量被改变了。在任何涉及副作用的表达式中,都可能存在对表达式中变量的更新顺序的微妙依赖。这种代码令人难受。来看一个典型的:

a[i] = i++;

问题是,数组下标用的是 i 的老值还是新值?不同的编译器可以用不同的方式来解释,并基于不同的解释生成不同的结果。标准有意地不明确规定大部分的这类问题。表达式中的副作用(对变量赋值)何时发生,这个决定权交给了编译器,因为最佳的选择强烈依赖于机器架构。(标准的确规定了,所有参数的副作用生效在函数被调用之前,但这无法解决上面的 printf 问题。)

结论就是:不管在任何语言中,写出依赖于求值顺序的代码都是糟糕的编程实践。自然地,有必要知道应该避免什么,但如果你不知道在各种不同的机器上是分别如何实现的,你也不会忍不住去利用某种特定的实现。

(第二章完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1156165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

0基础学习PyFlink——个数滚动窗口(Tumbling Count Windows)

大纲 Tumbling Count WindowsmapreduceWindow Size为2Window Size为3Window Size为4Window Size为5Window Size为6 完整代码参考资料 之前的案例中&#xff0c;我们的Source都是确定内容的数据。而Flink是可以处理流式&#xff08;Streaming&#xff09;数据的&#xff0c;就是…

go中url.ParseRequestURI和url.Parse函数的踩坑记

使用url.Parse函数 package mainimport ("fmt""net/url" )func main() {attrRawUrl : "http://localhost?wifitrue&carrier#Staysafe AIS&osandroid"urlObj, _ : url.Parse(attrRawUrl)fmt.Printf("urlObj:%#v\n", *urlObj)…

python 安装 pyquicklz 库函数

问题描述&#xff1a; 安装 pyquicklz 库的时候 报错 error: subprocess-exited-with-error 解决方法&#xff1a; 安装 Cython 库&#xff1a; pip install Cython -i https://pypi.tuna.tsinghua.edu.cn/simple/ 安装 Microsoft C Build Tools Microsoft C Build Tools 的下…

Spring MVC 续

一、拦截器 1.介绍拦截器 1.拦截器&#xff08;springmvc提供&#xff09; 2.只拦截控制单元&#xff08;生效必须配置拦截器&#xff09; 3.会拦截静态资源&#xff0c;使用拦截器时&#xff0c;尽量使用局部配置&#xff0c;配置拦截的控制单元即可。 注意&#xff1a;只…

python多环境并存

1. 现况简介 1.1 本人windows所存Python版本 Python 2.7 Python 3.6 Python 3.7 1.2 Python 各版本路径如下 Python 2.7Python 3.6Python 3.7C:\Server\Python27C:\Server\Python36C:\Server\Python37 1.3 系统环境变量配置如下 2. 解决方案 2.1 进入目录 cd C:\Server…

【机器学习】三、特征选择与稀疏学习

特征选择和稀疏学习 子集搜索与评价 对象都有很多属性来描述&#xff0c;属性也称为特征&#xff08;feature&#xff09;&#xff0c;用于刻画对象的某一个特性。对一个学习任务而言&#xff0c;有些属性是关键有用的&#xff0c;而有些属性则可能不必要纳入训练数据。对当前学…

win10 下编译ffmpeg3.36.tar.gz

所需工具&#xff1a; win10 ffmpeg3.36.tar.gz。 或其他版本&#xff0c;下载地址&#xff1a;Index of /releases msys2。 下载地址&#xff1a;http://www.msys2.org。 Visual Studio 2017。 1. 安装MSYS MSYS2像是windows下的一个子系统&#xff0c;…

`.NET Web`新人入门必学项目`EarthChat`

.NET Web新人入门必学项目EarthChat EarthChat是一个基于.NET 7的实战项目&#xff0c;EarthChat提供了很多的最佳实践&#xff0c;EarthChat的目标也是成为一个很多人都喜欢的大型聊天业务系统&#xff0c;并且将结合SKAI大模型进行打造智能业务系统&#xff0c;在EarthChat中…

05_es分布式搜索引擎1

一、初始elasticsearch 1.elasticsearch简单介绍 ①什么是elasticsearch&#xff1f; 开源的分布式搜索引擎&#xff0c;实现海量数据搜索&#xff0c;日志统计&#xff0c;分析&#xff0c;系统监控等功能 ②什么是elastic stack&#xff1f; 是以elasticsearch为核心的技…

【COMP304 LEC4 LEC5】

LEC 4 1. Truth-Functionality Propositional logic 的connectives&#xff08;连接词&#xff09;are truth-functional 但是&#xff0c;有时候的描述不是true-functional的&#xff0c;比如&#xff1a;"Knowing that", "It is necessary that",&quo…

微信小程序开发-微信支付退款功能【附有完整代码】

之前有写过详细的微信支付功能&#xff1a;微信支付 我们使用weixin-java-pay的jar包等&#xff0c;配置上的流程同微信支付&#xff0c;可以看上面的文章。 退款使用的WxPayService类的refundV3方法。使用该方法需要在微信支付配置的基础上加上&#xff1a;apiclient_key.pem…

Linux期末复习——多线程编程

线程概述 线程基本编程 函数说明 pthread_create(): 创建线程&#xff0c;成功返回0pthread_exit(): 主动退出线程&#xff0c;成功返回0pthread_join(): 挂起线程等待结束&#xff0c;成功返回0pthread_cancel在别的线程中终止另一个线程的执行&#xff0c;成功返回0 示例…

sql文件批处理程序-java桌面应用

项目效果&#xff1a; 支持sql文件夹批处理&#xff0c;选中文件夹或者sql文件 支持测试连接&#xff0c;可以校验数据库配置 支持报错回显&#xff0c;弹出报错文件名以及问题语句 支持在程序中修改错误语句&#xff0c;用户可以选择保存修改内容继续执行或不保存修改只执行…

线性代数 第四章 线性方程组

一、矩阵形式 经过初等行变换化为阶梯形矩阵。当&#xff0c;有解&#xff1b;当&#xff0c;有非零解。 有解&#xff0c;等价于 可由线性表示 克拉默法则&#xff1a;非齐次线性方程组中&#xff0c;系数行列式&#xff0c;则方程组有唯一解&#xff0c;且唯一解为 其中是…

TestCenter测试管理工具

estCenter&#xff08;简称TC&#xff09;一款广受好评的测试管理工具&#xff0c;让测试工作更规范、更有效率&#xff0c;实现测试流程无纸化&#xff0c;测试数据资产化。 产品概述 TC流程图 产品功能 一、案例库 案例库集中化管理&#xff0c;支持对测试用例集中管理&…

Gartner报告 | Mendix再次成为低代码领导者!Mendix在愿景完整性和执行能力领域的排名最为靠前。

本文作者: Hans de Visser, Mendix 首席产品官 在最新发布的2023 Gartner魔力象限图™ 中对于企业级低代码应用程序平台&#xff0c;Gartner指出&#xff0c;企业IT领导者需要满足“应用程序开发向更高抽象级别迈进的步伐&#xff0c;并采用低代码平台来加速应用程序开发。” 此…

【华为】路由器以PPPoE拨号接入广域网

组网需求 用户希望以PPPoE拨号方式接入广域网&#xff0c;如图1所示&#xff0c;Router作为PPPoE客户端&#xff0c;得到PPPoE服务器的认证后获得IP地址&#xff0c;实现用户接入互联网的需求。内网网关地址&#xff08;即VLANIF1接口的IP地址&#xff09;为10.137.32.1/24。 …

N-131基于jsp,ssm物流快递管理系统

开发工具&#xff1a;eclipse&#xff0c;jdk1.8 服务器&#xff1a;tomcat7.0 数据库&#xff1a;mysql5.7 技术&#xff1a; springspringMVCmybaitsEasyUI 项目包括用户前台和管理后台两部分&#xff0c;功能介绍如下&#xff1a; 一、用户(前台)功能&#xff1a; 用…

UE5 Android下载zip文件并解压缩到指定位置

一、下载是使用市场的免费插件 二、解压缩是使用市场的免费插件 三、Android路径问题 windows平台下使用该插件没有问题&#xff0c;只是在Android平台下&#xff0c;只有使用绝对路径才能进行解压缩&#xff0c;所以如何获得Android下的绝对路径&#xff1f;增加C文件获得And…