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

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.hqwc.cn/news/154734.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用示例和应用程序全面了解高效数据管理的Golang MySQL数据库

Golang&#xff0c;也被称为Go&#xff0c;已经成为构建强大高性能应用程序的首选语言。在处理MySQL数据库时&#xff0c;Golang提供了一系列强大的库&#xff0c;简化了数据库交互并提高了效率。在本文中&#xff0c;我们将深入探讨一些最流行的Golang MySQL数据库库&#xff…

【idea】生成banner.txt

Spring Boot banner在线生成工具&#xff0c;制作下载英文banner.txt&#xff0c;修改替换banner.txt文字实现自定义&#xff0c;个性化启动banner-bootschool.netSpring Boot banner工具实现在线生成banner&#xff0c;轻松修改替换实现自定义banner&#xff0c;让banner.txt文…

学习笔记|配对样本均数T检验|SPSS常用的快捷键|规范表达|《小白爱上SPSS》课程:SPSS第六讲 | 配对样本均数T检验

目录 学习目的软件版本原始文档配对样本均数T检验一、实战案例二、案例解析三、统计策略四、SPSS操作1、正态性检验2、配对样本T检验 五、结果解读六、规范报告1、规范表格2、规范文字 划重点Tips:SPSS常用的快捷键 学习目的 SPSS第六讲 | 配对样本均数T检验 软件版本 IBM S…

3 tensorflow构建模型详解

上一篇&#xff1a;2 用TensorFlow构建一个简单的神经网络-CSDN博客 1、神经网络概念 接上一篇&#xff0c;用tensorflow写了一个猜测西瓜价格的简单模型&#xff0c;理解代码前先了解下什么是神经网络。 下面是百度AI对神经网络的解释&#xff1a; 神经网络是一种运算模型&…

openEuler社区2023年度满意度调研

Hi&#xff0c;朋友们 一年一度的openEuler社区满意度调研来啦&#xff01;我们诚邀您参与问卷调研&#xff0c;反馈您在社区的使用情况。我们会持续吸纳建议&#xff0c;为您创造更好的用户体验&#xff01; 时间&#xff1a;2023年10月27日-2023年12月17日 。 链接&#x…

【Linux】第三站:Linux基本指令(二)

文章目录 一、通配符 *二、man指令三、cp指令1.先给一个文件里面写入数据2. cp指令拷贝普通文件3.cp指令拷贝文件目录4.常用的选项总结 四、mv指令1.mv命令简介2.使用 五、一些插曲1.一些注意事项2.指令的本质3.再谈输出重定向4.追加重定向5.输入重定向 六、cat指令七、more指令…

电脑录像功能在哪?一文帮你轻松破解

“电脑录像功能在哪里呀&#xff1f;最近因工作上的原因&#xff0c;需要使用电脑来录像&#xff0c;但是找了一上午都找不到在哪里&#xff0c;眼看已经快没时间了&#xff0c;现在真的很急&#xff0c;希望大家帮帮我。” 电脑已经成为了人们生活和工作中必不可少的工具&…

【ROS教程demo】用C++创建一个ROS节点,发布指令使得小海龟做圆周运动

ROS创建节点发布命令使得小海龟做圆周运动 1.任务需求2.任务分析2.1发布方topic和msg2.2接收方topic和msg2.3目标明确!3.创建ROS节点3.1创建发布方节点pub_pose3.2创建订阅方节点sub_pose1.任务需求 创建一个节点,在其中实现一个订阅者和一个发布者,完成以下功能: 发布者:…

Mac电脑配置Dart编程环境

1.安装Dart SDK 官网地址&#xff1a;https://dart.dev/get-dart $brew tap dart-lang/dart$brew install dart 安装后&#xff0c;用命令检测一下是否安装正常。 $brew info dart 2.VS Code配置Dart环境 1).安装VS Code 官网地址&#xff1a;https://code.visualstudio.c…

APP推荐:推荐一款免费无广告的本地音乐播放器,手机听歌必备

目录 一、软件简介 二、软件特色 三、软件使用 四、软件下载 相信很多朋友都喜欢听歌&#xff0c;今天给大家推荐一款非常棒的手机本地音乐APP——糖醋音乐&#xff0c;完全无广告、免费听歌&#xff0c;大家只需要把自己需要的歌曲下载到你的手机就可以愉快的听歌了&#…

Linux开发者的利器:深入了解环境开发工具之yum篇

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; &#x1f354;前言&#xff1a;在博主的博客中&#xff0c;Linux系统我们已经将关键指令、权限等等全部了解完了。接下来我们应该学习什么呢&#xff1f;当我们拿起一个手机或电脑&#xff0c;我们最先想到的就是下载QQ、…

SurfaceFliger绘制流程

前景提要&#xff1a; 当HWComposer接收到Vsync信号时&#xff0c;唤醒DisSync线程&#xff0c;在其中唤醒EventThread线程&#xff0c;调用DisplayEventReceiver的sendObjects像BitTub发送消息&#xff0c;由于在SurfaceFlinger的init过程中创建了EventThread线程&#xff0c…