allbet登陆官网:【C++和C#的区别杂谈】后自增运算符的结算时机

admin 4个月前 (06-26) 科技 55 0

C++和C#的前自增++n和后自增n++,都是先自增后取值先取值后自增的寄义,但在庞大一点的赋值语句中,我发现细节上有很大的差异。

发现这个问题主要是一个无聊的晚上,我想搞清楚后自增是什么时刻结算,自己捣鼓了一下之后我把我自己的测试效果告诉了同伙,效果学jAVa的同伙和我争论了半天,最后发现同样的代码,人人输出是不一样的。之后我又用了C#写了同样的测试代码,发现输出和他jaVa是一样的,这让我豁然开朗,遂写下这篇博客希望分享我的结论,若是有错误的话,迎接谈论区指正。

前排提醒:C++和C#我都是用的VS2017,差别编译环境的C++代码输出效果可能不一样

先说我的结论:

C++:i++遇到顺序点(逗号,分号)之后i才自增,即我一直以来以为的一条语句竣事后结算。但++i前自增的值会影响赋值语句所有i的值。

C#:C#不允许使用‘,’逗号运算符,但也并非到';'分号才结算,赋值语句是从左到右,按序取值,i++在取完i的值之后马上就自增了,但不影响之前取的i的值,只影响后续i的取值。

心得:现实开发照样只管自增单行写,第一个是可读性好,第二个是不容易出问题。(应该也就只有笔试会泛起以下实验的代码了)

结论看不明了的可以看看我无聊的小实验:

最简朴常见的版本:

int arr[] = { 0,0,0 };
int n = 0;
arr[n] = n++;//语句a
for (int num : arr)
{
	cout << num << ' ';
}
//输出是0 0 0,语句a竣事后n自增到1

上面这段代码其实在C#也是一样的输出,但若是下面这样写,效果就不一样了。

C++版:

int arr[] = { 0,0,0 };
int n = 0;
arr[n++] = n;//语句a
for (int num : arr)
{
	cout << num << ' ';
}
//输出是0 0 0,语句a竣事后n自增到1,C++效果和上面的一样

C#版:

int[] arr = { 0, 0, 0 };
int n = 0;
arr[n++] = n;//语句a
foreach (int num in arr)
{
	CoNSOle.Write(num + " ");
}
//输出是1 0 0,现在应该能明白结论了,从左到右,先取n作为索引值,然后自增之后影响到了等号右边的n的值
//语句a则为arr[0] = 1;

就是这样的差异最先引申出了问题,也是让我疑惑的最先,接下来我会通过更庞大的例子和反汇编的指令来注释和证实我的结论,先枚举C++的部门,之后再C#,感兴趣的可以往下看。

C++部门:

//代码01
int arr[] = { 0,0,0 };
int n = 0;
arr[n++] = n + (n++) + ++n;
for (int num : arr)
{
	cout << num << ' ';
}
//输出为0 3 0,详细操作流程为语句先结算了++n,使得n自增到1.而泛起的两个n++都在赋值语句竣事后结算
//以是编译效果为arr[1] = 1 + 1 + 1; 然后i自增两次到3

以下为反汇编的效果:

一最先看到这个我有点懵逼,然则通过比对下面这段代码的反汇编指令,就能看出来了。

//代码02
int[] arr = { 0, 0, 0 };
int n = 0;
arr[++n] = n + (n++) + ++n;//把索引处的n++改为了++n
foreach (int num in arr)
{
	CoNSole.Write(num + " ");
}
//输出为0 0 6,详细操作流程为语句先结算两次++n,使得n自增到2.而n++在赋值语句竣事后结算
//以是编译效果为arr[2] = 2 + 2 + 2; 然后i自增到3
//这下应该发现n在这条语句中取值的时刻都是同样的值了

以下为上面代码02的反汇编效果:

通过和上面的指令比对可以看出来了,详细差异在00251F3A这段指令,arr[++n]这段代码02在累加前多举行了一次对n的自增,然后将自增后的值赋给了n,然后最先举行累加,而上面arr[n++]那段代码01是在累加竣事之后,在01161F4A那条指令对n++举行自增的结算,以是就算看不懂所有的指令,也应该能通过比对这两段代码看出他们的差异,从而证实了C++对于后自增的处置,是在语句竣事之后结算

说到语句竣事,我之前写了一篇关于逗号运算符的博客,可以连系今天这个结论看看下面这段代码的输出效果。

int arr[] = { 0,0,0 };
int n = 0;
arr[n] = (n++, n + (n++) + ++n);//在逗号左边添加了n++的语句
for (int num : arr)
{
	cout << num << ' ';
}
//输出为0 0 6
//原由于逗号也属于一条语句竣事的标志,以是结算了n++,n=1,然后执行新的语句n + (n++) + ++n
//逗号右边的语句先结算了++n,n=2,以是最后赋值语句为arr[2] = 2 + 2 + 2; 然后n++到3

至此C++的部门竣事。

接下来C#的测试效果将推翻上面的结论,若是不用java或者C#的话,下面的内容可能没有用(同伙java的输出效果和我C#一样,不外也是希望人人自己试试,我自己没有试过)

C#部门:

//代码01 C#版
int[] arr = { 0, 0, 0 };
int n = 0;
arr[n++] = n + (n++) + ++n;
foreach (int num in arr)
{
	Console.Write(num + " ");
}
//输出为5 0 0 和VC++完全不一样对吧
//详细原由于C#的赋值语句是从左到右,先取了n的值作为索引,然后马上对n自增,n=1
//来到等号右边,第一个n取值为1,第二个n取值为1,然后自增到2,第三个n先自增到3,然后取值为3
//以是最终编译效果为arr[0] = 1 + 1 + 3;  即5 0 0的缘故原由
//为了节约篇幅,我直接告诉你arr[++n] = n + (n++) + ++n的效果为0 5 0,若是你上面看懂了这个应该也懂

贴一下C#这段代码的反汇编效果:

可以看到第一行是取n的值,然后把n作为索引值,之后inc指令对n自增1。证实了上面的结论。

即:C#的赋值语句为从左到右,按序取值,n++在取完n的值之后马上自增,但不影响之前取的值,只影响后续n的取值

小结:

以是++n 先自增后取值n++ 先取值后自增是能直接套在C#上的,而对于VC++来说,后自增的结算是异常“缓慢”的,到语句竣事才结算。

感谢您的旁观。

,

联博开奖

www.326681.com采用以坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。

皇冠APP声明:该文看法仅代表作者自己,与本平台无关。转载请注明:allbet登陆官网:【C++和C#的区别杂谈】后自增运算符的结算时机

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:530
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1050
  • 评论总数:164
  • 浏览总数:3768