摘要:

现行国内的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语言序列点浅析的更多相关文章

  1. C语言序列点问题总结(大多数高等教育C语言教学课程的漏洞)

    C语言序列点总结 2013年11月21于浙大华家池 C 语言副作用: (side effect)是指对数据对象或者文件的修改. 例如,语句 v = 99;的副作用是把 v 的值修改成 99. C语言序 ...

  2. ReactiveX序列——RxSwift 浅析

      ReactiveX序列——RxSwift Swift是苹果公司新推出的一门现代化的编程语言,并且将其开源出来了,Swift具有很多的优点,这也使得这门语言推出的短时间引起了很大反应的原因,在最近的 ...

  3. C语言之goto浅析

    1.  读代码时遇了的疑惑点: static int do_bind(const char *host, int port, int protocol, int *family) { int fd; ...

  4. C语言 序列反向互补函数

    1 static char *revers(char *s) 2 { 3 int len=strlen(s); 4 char *s2=(char *)malloc(sizeof(char)*(len+ ...

  5. 10. Go 语言反射

    Go 语言反射 反射是指在程序运行期对程序本身进行访问和修改的能力.程序在编译时,变量被转换为内存地址,变量名不会被编译器写入到可执行部分.在运行程序时,程序无法获取自身的信息. 支持反射的语言可以在 ...

  6. MTU-TCP/IP协议栈-linux kernel-TCP丢包重传-UDP高性能-AI-

    http://view.inews.qq.com/a/20161025A0766200窄带时代的QQQQ是窄带时代极具代表性的产品,在那个网络传输效率比较低的年代,大家还记得Google的首页吗?Go ...

  7. python的编码问题研究------使用scrapy体验

    python转码译码 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impo ...

  8. [转]语言模型训练工具SRILM

    SRILM是一个建立和使用统计语言模型的开源工具包,从1995年开始由SRI 口语技术与研究实验室(SRI Speech Technology and Research Laboratory)开发,现 ...

  9. 【OCR技术系列之五】自然场景文本检测技术综述(CTPN, SegLink, EAST)

    文字识别分为两个具体步骤:文字的检测和文字的识别,两者缺一不可,尤其是文字检测,是识别的前提条件,若文字都找不到,那何谈文字识别.今天我们首先来谈一下当今流行的文字检测技术有哪些. 文本检测不是一件简 ...

随机推荐

  1. java设计模式之三单例模式(Singleton)

    单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...

  2. Java小知识点学习--------数组和位运算小知识点

    位运算符: >>>无符号右移运算符,无符号右移的规则和右移的规则同样,仅仅是在填充时,无论原来是正数还是负数都用0来补充. 数组: arr1=arr2;  此时两个数组变量都会同一时 ...

  3. C#实现接口xml序列化与反序列化

    C#实现接口xml序列化与反序列化   C#中接口无法被xml序列化,提示不支持.百度和bing也搜不到,只好自己动手写了 原理上肯定支持,.Net自己的xml序列化有一个IXmlSerializab ...

  4. Web应用程序整体测试基础——单元测试

    近年来,随着基于B/S结构的大型应用越来越多,Web应用程序测试问题也在逐步完善中.但Web应用程序测试既可以在系统开发中实施,也可以独立于系统单独完成,这取决于Web应用程序的复杂性和多样性.同时程 ...

  5. Java集合之HashMap源码实现分析

    1.简介 通过上面的一篇随笔我们知道了HashSet的底层是采用Map实现的,那么Map是什么?它的底层又是如何实现的呢?这下我们来分析下源码,看看具体的结构与实现.Map 集合类用于存储元素对(称作 ...

  6. D3D 光照和材料 小样例

    1.实现一个旋转的圆柱体,体现d3d光照效果 2.程序实现 #pragma once #pragma comment(lib,"winmm.lib") #pragma commen ...

  7. 【分布式存储系统sheepdog 】

    Sheepdog,是由NTT的3名日本研究员开发的开源项目,主要用来为虚拟机提供块设备. 其架构例如以下: 以下,我们将从架构.模块等几个方面来介绍下: 一.架构图 如上图: 採用无中心节点的全对称架 ...

  8. Python框架之Django学习

    当前标签: Django   Python框架之Django学习笔记(十四) 尛鱼 2014-10-12 13:55 阅读:173 评论:0     Python框架之Django学习笔记(十三) 尛 ...

  9. Android项目---快递查询

    快递查询,快递100上有更多接口信息 1.快递查询的接口是 快递公司的code值+快递单号 进行的网络查询.第一步,怎么将快递公司的名字转换成code值,传递给接口.下面是快递公司以及对应的code值 ...

  10. AJAX跨域调用ASP.NET MVC或者WebAPI服务

    关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案 作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP. ...