热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于C/C++副作用与顺序点的问题

在学习c++primerplus过程中遇到了这个问题,查询大量资料后,我总结一下。首先看下面这个问题:intx1,y;yx++*(5+x++);prin

 
  在学习c++primer plus过程中遇到了这个问题,查询大量资料后,我总结一下。首先看下面这个问题: 
 
int x=1,y;
y = x++ * (5 + x++);
printf("x = %d,y = %d",x,y);
或者以C++写的:
int x=1,y;
y = x++ * (5 + x++);
cout< 
  根据以往做题的经验,你知道x++应先用值再递增,++x应先递增再用值。所以应该这么算y = 1 * (5 + 2) = 7,输出x = 3,y = 7。可是经过编译运行后,结果却是x = 3,y = 6。 
 
再来看几个:
int x1,x2,x3,x4;
x1 =x2 =x3 =x4= 2;
int y1,y2,y3,y4;
y1 = x1++ * (5-x1++);//2*(5-3)=4;
y2 = x2++ * (5-++x2);//2*(5-4)=2;
y3 = ++x3 * (5-x3++);//3*(5-3)=6;
y4 = ++x4 * (5-++x4);//3*(5-4)=3

cout< 想象中的答案应该是4,2,6,3,然而,控制台输出结果为6,6,6,4。
有人也许碰到过这个问题:

int x = 1;
x = 2 * x++ * (3 - ++x);
cout< 
  此时控制台输出结果为3,但是无论你怎么算也算不到是三,因为对此C++没有定义正确的行为。(以上结果在用c/c++写输出结果都是一致的。)出现这种情况的就是C/C++语句中顺序点和副作用的原因。 
 

副作用:在计算表达式时对某些东西(如变量里的值)进行了修改。
顺序点:程序执行过程中的一个点。 --《c++ primer plus》

C/C++规定,在执行过程中,每当执行到一个顺序点,则该顺序点之前的副作用都应该执行完成,即编译器保证在执行到每一个顺序点时,完成前面的副作用评估,然而在连个顺序点之间到底按什么顺序执行并不能保证。
这就解释了之前这个问题:
x1 = 2;
y1 = x1++ * (5-x1++);//2*(5-3)=4;
cout< 
  一个分号就是一个完整的句子,因此该分号就是一个顺序点。而x1++跟(5 - x1++)并不是完整的句子,因此不能 成为顺序点。因此,这三句有三个顺序点。有三个副作用,两个x1递减和一个赋值给y1.在第二个顺序点时,x1的值完成了两个副作用,可以通过下面的cout证明。但是y1的值却并没有得到想象中的结果,编译器没有根据的你顺序去执行。他只保证了分号结束时x1的值会增加2,但具体以什么样的顺序执行却没有保证。 
 
另外标准还规定,两个相邻顺序点之间,对某一表达式求值,最多只能造成任一特定对象的值被更改一次。如果表达式求值过程会更改某对象的值,那么要求更改前的值被读取的唯一目的,只能是用来确定要存入的新值。
但是实际来看,有很多情况都违反了这个规定。例如上面的x1的值就被更改了两次。具体原因未解。
因此在实际运用中,我们要避免这样的语句。因为他的结果往往是不确定的。其实,实际运用中很少会用到类似y1 = x1++ * (5-x1++);这样的语句吧,除非你在准备考试。。
补:c标准定义顺序点在:
1. 每个完整表达式结束时。完整表达式包括变量初始化表达式,表达式语句,return语句的表达式,以及条件、循环和switch语句的控制表达式(for头部有三个控制表达式);
2. 运算符 &&、||、?: 和逗号运算符的第一个运算对象计算之后;
3. 函数调用中对所有实际参数和函数名表达式(需要调用的函数也可能通过表达式描述)的求值完成之后(进入函数体之前)。
假设时刻ti和ti+1是前后相继的两个顺序点,到了ti+1,任何C/C++ 系统(VC、BC等都是C/C++系统)都必须实现ti之后发生的所有副作用。当然它们也可以不等到时刻ti+1,完全可以选择在时段 [t, ti+1] 之间的任何时刻实现在此期间出现的副作用,因为C/C++ 语言允许这些选择。
参考文章:http://blog.csdn.net/gexueyuan/article/details/9770063 点击打开链接

   http://www.tuicool.com/articles/fUBvma点击打开链接

  http://www.cnblogs.com/smwikipedia/articles/1229984.html点击打开链接



推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 以指针引入:指针本身是一个对象,它又可以指向另一个对象。因此,指针本身是不是常量以及指针所指的是不是一个常量就是俩个相互独立的问题。用顶层const表示指针本身是一个常量;用底层con ... [详细]
  • [置顶]        C++类的构造函数与析构函数的调用顺序
    1构造函数的调用顺序[1]构造函数按此顺序执行工作:按声明顺序调用基类和成员构造函数。如果类派生自虚拟基类,则会将对象的虚拟基指针初始化。如果类具有或继承了虚函数,则会将对象的虚函数指针初始化。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • C++ OpenCV实战之标记点检测的实现
    C++ OpenCV实战之标记点检测的实现-在实际应用中,能够直接利用霍夫圆检测这些理想方法的应用场景是非常少的,更多的是利用拟合的办法去寻找圆形。大致思路如下,首先先选择要处理的 ... [详细]
  • YoucanSolveaGeometryProblemtooProblemDescriptionManygeometry(几何)problemsweredesignedinth ... [详细]
  • AtonepointIhadlookedatimplementingaclasstemplateinC++thatwouldsupportanEnumthatwo ... [详细]
  • STL学习笔记--数值算法
    数值算法  C++STL的数值算法(Numericalgorithms)是一组对容器元素进行数值计算的模板函数,包括容器元素求和accumulate、两序列元素的内积inner_pro ... [详细]
  • SayIhaveafunctionwork(),onceitiscalled,Idontwantittobecalledinthenext5seconds. ... [详细]
author-avatar
贾章鱼_977
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有