C++求值顺序
《C++Primer5th》中文版第124页
C++语言没有明确规定大多数二元运算符的求值顺序,
给编译器优化留下了余地。
这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,这个是否可以接受?
1.首先可以知道优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。
比如:
int i=f1()*f2();
在这里虽然f1和f2在乘法之前被调用,但是f1先调用还是f2先调用却不得而知。
2.再比如结合律
int i=0;
cout<<i<<" "<<++i<<endl;
结果可能是0 1或者是1 1.
因为虽然<<是左结合,但是对于那些没有明确规定运算对象的求值顺序的运算符而言,求值顺序就和优先级,以及结合律无关。
所以上面的式子是未定义的,即如果表达式指向并且修改了同一个对象,这样的行为就是未定义的
- 逻辑与&&
- 逻辑非||
- 条件?:
-逗号,
上面四种运算符明确规定了运算对象的求值顺序。
3.C++手册
几乎所有 C++ 运算符的求值顺序(包括函数调用表达式中的函数参数求值顺序和任何表达式中子表达式的求值顺序)都是未指定的。编译器能以任何顺序求值,并可以在再次求值相同表达式时选择另一顺序。
例子:
表达式 f1() + f2() + f3()
由于 operator+ 的从左到右结合性分析为 (f1() + f2()) + f3() ,但运行时对 f3 的函数调用可能首先、最后,或在 f1() 和 f2() 之间求值。
4.序列点规则(以下内容来自C++手册)
序列点规则 (C++11 前)
定义
求值可能产生副效应:即访问 volatile 左值所指代的对象、修改对象、调用库 I/O 函数或调用做任何这些动作的函数。
序列点( sequence point )是执行序列中的点,在该点所有来自序列中先前求值的副效应均已完成,而后继求值的副效应都未开始。
规则
每个完整表达式结尾(典型地在分号)有一个序列点。
调用函数时(无论该函数是否内联,无论是否使用函数调用语法),所有函数参数的求值(若存在)后有一个序列点,它在函数体内的任何表达式或语句执行前发生。
复制函数返回值后,和函数外任何语句的执行前有一个序列点。
一旦函数执行开始,则在被调用函数完成前,不求值来自调用方函数的表达式(函数不能交错)。
每个使用内建(非重载)运算符的下列四种表达式的求值中,表达式 a 的求值后有一个序列点。
a && b
a || b
a ? b : c
a , b
未定义行为
- 前后序列点间,至多可以修改标量对象的存储值一次,否则行为未定义。
i = ++i + i++; // 未定义行为
i = i++ + 1; // 未定义行为( C++17 前)
i = ++i + 1; // 未定义行为( C++11 前)
++ ++i; // 未定义行为( C++11 前)
f(++i, ++i); // 未定义行为( C++17 前)
f(i = -1, i = -1); // 未定义行为( C++17 前)
- 前后序列点间,访问表达式求值所修改的标量对象的先前值,必须只为确定要存储的值。若以任何其他方式访问,则行为未定义。
cout << i << i++; // 未定义行为( C++17 前)
a[i] = i++; // 未定义行为( C++17 前)
C++求值顺序的更多相关文章
- 诡异的C语言实参求值顺序
学了这么久的C语言,竟然第一次碰到这么诡异的实参求值顺序问题,大跌眼镜.果然阅读面太少了! #include<iostream> void foo(int a, int b, int c) ...
- 【部分原创】标准C语言的优先级、结合性、求值顺序、未定义行为和非确定行为浅析
零. 优先级 在C++ Primer一书中,对于运算符的优先级是这样描述的: Precedence specifies how the operands are grouped. It ...
- &&、||、?:、,四个运算符的求值顺序
C语言中只有四个运算符(&&.||.?:.,)存在规定的求值顺序. 运算符&&和运算符||首先对左侧操作数求值,只在需要时才对右侧操作数求值. 运算符?:有三个操作数: ...
- SQL AND和OR求值顺序
假如需要列出价格为10美元及以上,且由DLL01或BRS01制造的所有产品.下面的SELECT语句使用组合的AND和OR操作符建立了一个WHERE子句: ; 分析▼ 请看上面的结果.返回的行中有4行价 ...
- C语言对表达式的求值顺序不是明确规定的
讨论区看到的 WA来自那些递归下降求解的代码. 第一种情况,使用|| 和 &&: 例如s为所给串 int getval() { switch(s[c_s++]) { case 'p': ...
- ZT C,C++表达式求值顺序 裘老的解释。 [问题点数:300分]
http://bbs.csdn.net/topics/370153775 [置顶] [推荐] C,C++表达式求值顺序 裘老的解释. [问题点数:300分] 最近这问题有从日经变时经的趋势,这里贴出裘 ...
- 连续赋值与求值顺序var a = {n:1};a.x = a = {n:2}; alert(a.x);
代码如下: <script> var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x);// --> undefined ...
- 左求值表达式,堆栈,调试陷阱与ORM查询语言的设计
1,表达式的求值顺序与堆栈结构 “表达式” 是程序语言一个很重要的术语,也是大家天天写的程序中很常见的东西,但是表达式的求值顺序一定是从左到右么? C/C++语言中没有明确规定表达式的运算顺序(从左到 ...
- C/C++ 语言中的表达式求值(原文作者:裘宗燕)
经常可以在一些讨论组里看到下面的提问:“谁知道下面C语句给n赋什么值?”m = 1; n = m+++m++;最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4, ...
随机推荐
- python-requests 简单实现数据抓取
安装包: requests,lxmlrequest包用于进行数据抓取,lxml用来进行数据解析对于对网页内容的处理,由于html本身并非如数据库一样为结构化的查询所见即所得,所以需要对网页的内容进行分 ...
- js之闭包
函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个对Array的求和.通常情况下,求和的函数是这样定义的: function sum(arr) { ret ...
- 位运算(6)——Number Complement
Given a positive integer, output its complement number. The complement strategy is to flip the bits ...
- Bootstrap导航栏navbar源码分析
1.本文目地:分析bootstrap导航栏及其响应式的实现方式,提升自身css水平 先贴一个bootstrap的导航栏模板 http://v3.bootcss.com/examples/navbar- ...
- C#中.Net的值传递和引用传递
/// <summary> /// 电脑类 /// </summary> public class Computer { public string Type { get; s ...
- 菜鸟学习Spring——SpringMVC注解版控制层重定向到控制层
一.概述. SpringMVC中界面请求Contorller1,Contorller1需要重定向到Contorller2中显示其他页面或者做一些业务逻辑,Spring中提供了这个功能利用"r ...
- linux C之判断文件或目录是否存在 access函数
http://blog.sina.com.cn/s/blog_6a1837e90100uh5d.html access():判断是否具有存取文件的权限 相关函数 stat,open,chmod, ...
- 大数据的正确用法你get到了吗?
Azure 镜像市场已于2016年9月21日正式上线,在这个统一的集成平台中,客户可以轻松地浏览.搜索和选择一系列来自第三方的应用和解决方案,并可以将其快速一键部署到 Azure 实例当中. 在移动为 ...
- EM自动任务导致数据库缓慢
这两天客户抱怨数据库慢,查看性能什么的没发现什么异常.查看job发现一个内容为EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS执行特别频繁.使用 EXEC DBMS_ ...
- Wi-Fi
AP就是一个无线的交换机,提供无线信号发射接收的功能 Wi-Fi是一种可以将个人电脑.手持设备(如PDA.手机)等终端以无线方式互相连接的技术 两个不一样的东西,无法比较的 你说的应该是无线路由器和无 ...