C语言序列点浅析
摘要:
现行国内的C语言教材普遍不介绍序列点,这使得读者只能“死记硬背”有序列点表达式的求值顺序,不仅造成了读者对C语言知识的认知残缺不全,而且也影响了读者学习的积极性。本文总结了序列点的作用,即表达式求值时需考虑序列点的影响,序列点左边的操作数要先于其右边的操作数求值。结合操作符的作用,分析了逗号操作符,、逻辑与操作符&&、逻辑或操作符||和条件操作符?:的问号处?为什么会有序列点。
关键字:序列点 表达式 C语言
C语言是最重要的结构化程序设计语言,许多编程语言如Java、C++、C#都借鉴了C语言的语法。随着数字化信息技术的发展和网络环境的形成,计算机已渗透到各行各业,为了更好地了解和使用计算机,国内大专院校的许多理工类专业都开设了C语言课程,因此,C语言的教学水平影响着许许多多的学生。
现行国内的C语言教材通常不介绍序列点,这使得读者只能“死记硬背”有序列点表达式的求值顺序。以简单的逗号表达式为例,设变量a为整型变量(下文中出现的变量a也为整型变量),在分析表达式a = 3, ++a的求值顺序时强调“逗号表达式自左向右依次求值”,而在分析表达式求值的原则时强调根据操作符的优先级和结合性确定求值顺序。即使表达式中自增操作符++的优先级最高,也要先对子表达式a=3求值,该怎样向学生解释这与求值原则矛盾的“求值顺序”呢?
1序列点的定义及分析
根据C语言标准[1][2][3],序列点就是执行序列中的一些特定点,在这些点上,前面求值的副效应(side effect)应彻底完成且其后求值的副效应均未发生。在教材中照搬标准让初学者学习理解序列点这个概念是不明智的,应直接向初学者指出序列点在表达式求值中起的作用。C语言表达式求值的原则为:根据操作符的优先级和结合性确定表达式的求值顺序,但求值时要考虑序列点的影响,需保证序列点左边的操作数先于其右边的操作数求值。
2操作符的操作数
操作数是指操作符进行操作的操作对象,如表达式3+2中加法操作符左边的操作数为3,右边的操作数为2。在复杂的表达式中,需结合操作符的优先级和结合性来确定某操作符的操作数。对于表达式3+2*5,加法操作符左边的操作数为3,但其右边的操作数不为2,因为进行加法运算时3不可能和2相加,其右边的操作数为2*5(的积);而乘法操作符左边的操作数为2,右边的操作数为5。
表达式a = 0 && ++a中逻辑与左边的操作数为0,右边的操作数为子表达式++a,整个表达式为赋值表达式;而表达式(a = 0) && ++a中逻辑与左边的操作数为子表达式(a = 0),右边的操作数为子表达式++a,整个表达式为逻辑表达式。
3C语言中有序列点的操作符
逗号操作符,有序列点。逗号操作符的作用为把多条语句变成一条语句,如a = 2;和++a;为两条语句,而a = 2, ++a;是一条语句。语句a = 2, ++a;执行时,如果逗号操作符没有序列点,子表达式++a就会先执行,即这条语句的执行顺序与上面两条语句的并不相同。基于逗号操作符的作用,逗号操作符只能优先级最低,且含有序列点。
逻辑与操作符&&有序列点。C语言中逻辑与操作符会“短路计算”,即当其左边的操作数为假时,不对右边的操作数求值而直接把0(假)作为结果。表达式3>5 && ++a求值时,如果逻辑与操作符没有序列点,子表达式++a就会先执行,即逻辑与操作符的短路计算名存实亡。为了短路计算,逻辑与操作符&&需序列点。求值时需保证序列点左边的操作数要先于其右边的操作数求值,故表达式3>5 && ++a中逻辑与操作符左边的操作数先求值,即子表达式3>5先求值,结果为0,即假,由于短路计算,整个表达式的值为0,即假,且右操作数子表达式++a不会被求值。
逻辑或操作符||有序列点。C语言中逻辑或操作符也会“短路计算”,因此,其有序列点的必要性与逻辑与的相同。
条件操作符?:的问号处?有序列点。条件操作符用于改写简单的if-else选择结构,如下面的语句(设变量b为整型变量)
if(a > b)
++a;
else
++b;
可用条件操作符改写为a > b ? ++a : ++b;。
如果条件操作符没有序列点,语句a > b ? ++a : ++b;执行时,++a和++b会先于子表达式a > b执行,这样的执行顺序显然与if-else选择结构的不同,因此,条件操作符?:的问号处?有序列点。语句a > b ? ++a : ++b;执行时,问号处?左边的操作数a > b先执行,值为真时,对++a求值,不对++b求值;值为假时,正好相反。
4结束语
虽然C语言表达式种类繁多,但表达式求值时有着相对明确的求值规则,只要根据求值规则分析,再奇特的表达式也不会成为学习上的难点。表达式求值时需考虑序列点的影响,忽视它的存在就不能正确地分析C语言表达式的求值顺序,只能让学生“死记硬背”,影响学习积极性。在教材中直接引入序列点的概念势必会增加学习的难度,从序列点在表达式求值中的作用入手,给初学者提供一个容易理解的序列点概念,不仅不会造成C语言知识点的残缺,而且也为“启发式教学”提供了可能,如可以引导初学者分析操作符为什么要有序列点。
参考文献
[1] International Organization for Standardization. ISO/IEC 9899:1999.
[2] International Organization for Standardization. ISO/IEC 9899:1990.
[3]国家技术监督局. GB/T 15272-94 程序设计语言 C. 1994
[4]周二强. C语言内涵教程[M]. 中国铁道出版社 2013.
C语言序列点浅析的更多相关文章
- C语言序列点问题总结(大多数高等教育C语言教学课程的漏洞)
C语言序列点总结 2013年11月21于浙大华家池 C 语言副作用: (side effect)是指对数据对象或者文件的修改. 例如,语句 v = 99;的副作用是把 v 的值修改成 99. C语言序 ...
- ReactiveX序列——RxSwift 浅析
ReactiveX序列——RxSwift Swift是苹果公司新推出的一门现代化的编程语言,并且将其开源出来了,Swift具有很多的优点,这也使得这门语言推出的短时间引起了很大反应的原因,在最近的 ...
- C语言之goto浅析
1. 读代码时遇了的疑惑点: static int do_bind(const char *host, int port, int protocol, int *family) { int fd; ...
- C语言 序列反向互补函数
1 static char *revers(char *s) 2 { 3 int len=strlen(s); 4 char *s2=(char *)malloc(sizeof(char)*(len+ ...
- 10. Go 语言反射
Go 语言反射 反射是指在程序运行期对程序本身进行访问和修改的能力.程序在编译时,变量被转换为内存地址,变量名不会被编译器写入到可执行部分.在运行程序时,程序无法获取自身的信息. 支持反射的语言可以在 ...
- MTU-TCP/IP协议栈-linux kernel-TCP丢包重传-UDP高性能-AI-
http://view.inews.qq.com/a/20161025A0766200窄带时代的QQQQ是窄带时代极具代表性的产品,在那个网络传输效率比较低的年代,大家还记得Google的首页吗?Go ...
- python的编码问题研究------使用scrapy体验
python转码译码 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impo ...
- [转]语言模型训练工具SRILM
SRILM是一个建立和使用统计语言模型的开源工具包,从1995年开始由SRI 口语技术与研究实验室(SRI Speech Technology and Research Laboratory)开发,现 ...
- 【OCR技术系列之五】自然场景文本检测技术综述(CTPN, SegLink, EAST)
文字识别分为两个具体步骤:文字的检测和文字的识别,两者缺一不可,尤其是文字检测,是识别的前提条件,若文字都找不到,那何谈文字识别.今天我们首先来谈一下当今流行的文字检测技术有哪些. 文本检测不是一件简 ...
随机推荐
- 第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例(原创)
天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...
- PHP 13: 类
原文:PHP 13: 类 Notice: This article is working on progress!本章将介绍PHP类.现在,基本上每种语言都支持面向对象,当然PHP也不列外.PHP在以 ...
- 【剑指offer】员工年龄排序
典型的以空间换时间问题,思路非常重要! /* 员工年龄排序 员工可能有几万名,要求时间复杂度为O(n) 思路:员工的年龄必定在一个范围内,比方0-99,那么我们建立一个大小为100的辅助数组,然后遍历 ...
- [转]Android与电脑局域网共享之:Samba Server
大家都有这样的经历,通过我的电脑或网上邻居访问另一台计算机上的共享资源,虽然电脑和手机之间可以有多种数据传输方式,但通过Windows SMB方式进行共享估计使用的人并不是太多,下面我就简单介绍一下, ...
- Javascript中布尔运算符的高级应用
对象检测语句:var W3CDOM = document.getElementsByTagName && document.createElement 为了执行运算符&& ...
- RMAN duplicate from active 时遭遇 ORA-17627 ORA-12154
最近在从活动数据库进行异机克隆时碰到了ORA-17629,ORA-17627,ORA-12154的错误,起初以为是一个Bug呢.Oracle Bug着实太多了,已经成了习惯性思维了.汗!错误提示是无法 ...
- OpenGL Development Cookbook chapter7部分翻译
让我们通过以下简单步骤开始我们的配方: 1.通过读取外部的体数据文件,并通过该加载数据集数据转换成一个OpenGL纹理.也使硬件的mipmap生成.通常情况下,从使用一个横截面中获得的体积数据文件存储 ...
- oracle琐碎笔记
Oracle知识点 ps:由于是自己看的所以笔记比较乱,大家谅解 Commit rollback Sql核心语句之select Selct中要用到以下语句 From语句 Where语句 Group b ...
- IOS UI 第九篇: UITABLEVIEW
学英语.所以用英文来记录笔记. Define the dataSource: @implementation ViewController{ NSMutableArray *dataSo ...
- Push Notification总结系列(二)
Push Notification系列概括: 1.Push Notification简介和证书说明及生成配置 2.Push Notification的iOS处理代码和Provider详解 3.Push ...