由变量值交换编程题想到的(C++与Java机制的不同)
今天网上看到一个老套的编程题,就是“不用第三个变量进行两个变量的值交换”。是一个同学把java写的答案放在网上求别人解析一下。平时因为做题用的都是C++,所以好奇瞄了一眼,却发现实现方法与C++截然不同,并且,Java和C++算数表达式解析的机制也存在很大不同。好吧,我们先来看看这个例子吧。
Java实现:(本文出自:http://my.oschina.net/happyBKs/blog/416632)
public static void main(String[] args) { // TODO Auto-generated method stub int x=4; int y=5; x=y+(y=x)*0; System.out.println("x="+x+", y="+y); }
结果是:
x=5, y=4
这里我如果将表达式改为x=(y=x)*0+y;
那么结果就是 x=4, y=4
这个例子,我相信大家能猜出其中的原因:Java在解析表达式时是从左向右执行的。
详细地说,在这个赋值语句中,先执行右边的算数表达式。执行之前x=4, y=5
算术表达式又按照从左到右的顺序执行,最左边y+先执行。这时候 x=4, y=5.没有任何变化
右边是(y=x)*0再从左向右看,首先是(y=x),执行之后,x=4, y=4. y变了!
(y=x)*0显然是0。
(y=x)*0+y则是0+y=0+4=4,赋给了赋值表达式左边的x。这时候,x=5, y=4
那么,如果在C++中的话,会怎么样呢?
代码和结果是这样的:
#include <iostream> #include <stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char** argv) { int x=4; int y=5; //x=(y=x)*0+y; x=y+(y=x)*0; printf("x=%d, y=%d",x,y); system("pause"); return 0; }
我将x=(y=x)*0+y;和x=y+(y=x)*0;两个表达式都实验了一下。结果答案都是:
x=4,y=4
这似乎说明了,在解析算数表达式时,执行不存在像Java那样的从左到右的顺序。同时,也不是从右向左的。
C++中的执行更像是这样一种情况执行了这样一个内联函数。(我推测的)
x=4,y=5
inline void fn(int x1, int y1)
{
x1=x;
y1=y;
y=x1;
x=y1+y1*0;
}
这似乎有点还是令人难以信服。那么我们就彻底跑个题吧,来看两个一样的代码例子,但是分别放到了Java和C++编译和运行环境中。
在java中的一个例子:
public static void main(String[] args) { int a=1; int b,c,d; d=(b=a++)+(c=a++)+(a++); System.out.println("a="+a+", b="+b+", c="+c+", d="+d); }
运行结果:
a=4, b=1, c=2, d=6
在C++中:
#include "stdafx.h" #include <stdlib.h> int _tmain(int argc, _TCHAR* argv[]) { int a=1; int b,c,d; d=(b=a++)+(c=a++)+(a++); printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d); system("pause"); return 0; }
运行结果:
上面的C++代码在gcc和VC下都进行了测试。
如果我把上面的例子再改一下。改为:
java:
public class TestMain { public static void main(String[] args) { int a=1; int b,c,d; d=(b=++a)+(c=++a)+(++a); System.out.println("a="+a+", b="+b+", c="+c+", d="+d); }
运行结果:
a=4, b=2, c=3, d=9
C++:
#include "stdafx.h" #include <stdlib.h> int _tmain(int argc, _TCHAR* argv[]) { int a=1; int b,c,d; d=(b=++a)+(c=++a)+(++a); printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d); system("pause"); return 0; }
运行结果:
看到了吧。似乎这时候,C++表达式也存在了从左到右的特性。Java任然亘古不变。
是不是有点晕了,C++到底怎么了?
那么我们单独再为C++设置一个例子:这次咱们里面都是赋值。
int a=1, b=10, c=100, d=1000; d=(b=a)+(c=b)+a; printf("a=%d, b=%d, c=%d, d=%d",a,b,c,d); system("pause"); return 0; }
结果是:
在修改个例子:如果d=(b=a)+(c=b)+++a;
运行结果是:
从上面的例子中已经可以看出我们之前下的结论了:Java在解析算数表达式时是从左向右执行的。C++解析算数表达式时, ++在前的因式需要在计算时就结算,并且从左向右执行。而=赋值则更像是在调用一个封装了算术表达式和赋值功能的内联函数。++在后的变量的累加操作在整个大表达式计算完成得到值之后结算。(还是整个表达式赋值之后结算?其实是等价的)
本文来自云栖社区合作伙伴“开源中国”
本文作者:HappyBKs
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
OSS 跨域配置
跨域问题可以通过脚本检查了 https://help.aliyun.com/document_detail/92151.html?spm=a2c4g.11186623.6.1275.41ab334esuiZHk 开启学习之旅 一个资源请求一个其它域名的资源时会发起一个跨域 HTTP 请求 cross-origin HTTP request 比如说,域名A http://domaina.example 的某 Web 应用通过 <img> 标签引入了域名 B http://domainb.foo 的某图片资源 http://domainb.foo/image.jpg 域名 A 的 Web 应用就会导致浏览器发起一个跨域 HTTP 请求。 http://www.123.com/index.html 调用 http://www.1
- 下一篇
深入理解Java中的volatile关键字
本文就围绕volatile展开,主要介绍volatile的用法、volatile的原理,以及volatile是如何提供可见性和有序性保障的等。 volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。尤其在C语言、C++以及Java中,都有volatile关键字。都可以用来声明变量或者对象。下面简单来介绍一下Java语言中的volatile关键字。 volatile的用法 volatile通常被比喻成"轻量级的synchronized",也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是一个变量修饰符,只能用来修饰变量。无法修饰方法及代码块等。 volatile的用法比较简单,只需要在声明一个可能被多线程同时访问的变量时,使用volatile修饰就可以了。 publicclassSingleton{ privatevolatilestaticSingletonsingleton; privateSingleton(){} publicstaticSingletongetSingleton()...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 设置Eclipse缩进为4个空格,增强代码规范
- Mario游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池