C++ 指针自增与指针取引用自增运算优先级探究


看不懂标题?没关系直接拿下面示例1代码试一下就会发现问题了,也就懂这个标题含义了

cout输出指针自增(*p++)运算示例1

示例来源

#include <iostream>
using namespace std;
int main()
{
	char s[] = "012345678", *p = s;

	cout << "s:" << s << endl;
	cout<< "*p++   = " << *p++ << endl
		<< "*(p++) = " << *(p++) << endl
		<< "(*p)++ = " << (*p)++ << endl
		<< "*++p   = " << *++p << endl
		<< "*(++p) = " << *(++p) << endl
		<< "++*p   = " << ++*p << endl
		<< "++(*p) = " << ++(*p) << endl;
	cout << "-------------------" << endl;

	char s1[] = "012345678";
	p = s1;
	cout << endl << "s1:" << s1 << endl;
	//cout << "*p     = " << *p << endl;
	cout << "*p++   = " << *p++ << endl;
	//cout << "*p     = " << *p << endl;
	cout << "*(p++) = " << *(p++) << endl;
	//cout << "*p     = " << *p << endl;
	cout << "(*p)++ = " << (*p)++ << endl;
	//cout << "*p     = " << *p << endl;
	cout << "*++p   = " << *++p << endl;
	//cout << "*p     = " << *p << endl;
	cout << "*(++p) = " << *(++p) << endl;
	//cout << "*p     = " << *p << endl;
	cout << "++*p   = " << ++*p << endl;
	//cout << "*p     = " << *p << endl;
	cout << "++(*p) = " << ++(*p) << endl;
	cout << "-------------------" << endl;

	system("pause");
	return 0;
}


测试结果
在这里插入图片描述

第一次原因分析

经过前后两端代码及输出结果对比发现结果大相径庭
可以将后面一段用来对比的代码已经没有多大意义了,可以直接注释掉,添加cout<<s<<endl;输出字符数组的值用于对比
结果为:213345678;
在这里插入图片描述
发现字符数组主要在前面部分发生改变

第一次源代码分析(错误,存在局限性)

其中包含
地址++   2个
值    ++   1个
++地址   2个
++值       2个
可简明地用下表表示:

++i 类别 i++
2个 地址 2个
2个 1个

则对比前后的s数组的值:
012345678
213345678
容易发现:++值发生在s[0],值++发生在s[2]。所以推测语句执行顺序是
++值>>++地址>>执行所在语句>>值++>>地址++
对比示例实验结果验证
++值 ++址 值++均为理论推导
址++为实验需要验证
通过在这句输出语句后再输出*pi

第一次理论推导:

++值
012345678//指针指向s[0]
112345678//指针指向s[0]
212345678//指针指向s[0]
++址
212345678//指针指向s[1]
212345678//指针指向s[2]
输出语句:
p++=//注意:这里++是在这条语句执行完后++,而不是输出了p++后执行++ 后面以此类推

值++
213345678//指针指向s[2]
址++
213345678//指针指向s[3]
213345678//指针指向s[4]

第一次实验验证:

cout<< *p<<endl;
结果:
在这里插入图片描述
与理论推导结果相符

第一次结论(错误,存在一定的局限性):

++值>>++地址>>执行所在语句>>值++>>地址++

cout输出指针自增(*p++)运算示例2

在私下用一段代码测试第一次得到的结论时,发现错误。
代码如下

	char s[] = "012345678", *p = s;
	
	cout << *p <<endl<<*p++<< endl<<endl;//10
	
	//地址前自增
	cout << *++p <<endl<<*p<< endl<<endl;//11
	cout << *++p <<endl<<*++p<< endl<<endl;//33
	cout << *p <<endl<<*++p<< endl<<endl;//44

矛盾:
1.前面理论推导部分的假设为:这里++是在这条语句执行完后++,而不是输出了*p++后执行++
结论一预期输出为 0 0 实际输出 1 0
2.为了在输出中产生1这个数字并且不放弃之前得出的结论,提出新假设:p++与*++p同等地位,即p++与*++p都会在执行该语句时先自增。
产生新矛盾:在这样的假设下应该为0 1,而不是1 0

摘自他人结论

百思不得其解,百度,得到以下结果:点我查看原文

计算顺序:自右至左
输出顺序:自左至右
什么意思呢,其实意思就是说
cout里面的所有的计算都会从右向左执行,然后把结果放回原位,再直接从左往右输出

根据该结论进行以下测试:

测试用例1:

	char s[] = "012345678", *p = s;
	//地址前自增
	cout << *++p <<endl<<*p<< endl;
	cout << *++p <<endl<<*++p<< endl;
	cout << *p <<endl<<*++p<< endl;

预期:11 33 44
结果:
在这里插入图片描述
正确

测试用例2:(验证从从右往左计算 从左往右输出)

测试代码

	int i = 0;
	cout << i << i++;//1 0

预期结果: 00
实验结果: 10
在这里插入图片描述
原因分析:
对于后自增运算与输出语句执行顺序不了解,于是进行下面一个测试;

测试用例3:(后自增运算与输出语句执行 顺序)

测试代码

	int i = 0;
	cout << i++ << i << endl;
	cout << i << i++ << endl;
	cout << ++i << i++ << endl;
	cout << i++ << ++i << endl;

根据之前最开始时第一次的实验结论加上本次实验的测试用例2得到的数据猜想:语句会先执行i++,再执行输出语句,每执行完一小句(<<之间为一小句)就会紧接着执行后自增,而非像第一次实验的假设那样执行完cout再后自增;

预期结果:
00
21
42
55
在这里插入图片描述
结果分析
之所以第一句与预期不同而输出01
提出假设一:后自增从右到左,左到右输出与后自增。
但在进行该假设验证过程中,发现了一个更合理的假设
假设二:输出时<<i<<并不算一个运算,只有i++之类的才算运算
其实在这次测试第一次预期时cout << i++ << i << endl;就忽略了这一点,即输出时从右向左运算时i由于不是运算,即并不会把后一个i的值计算出来即并不会把i当成1存回去而是直接进行下一个i++的计算得到第一个i=0再输出下一个i=1

测试用例4:

还没来得及测就被吓傻了
在这里插入图片描述
在这里插入图片描述
赶紧百度+谷歌
搜到以下结果:点我查看原网址
在这里插入图片描述

无心再测了,自闭…

cin中的<<其实是一个重载了的operator <<,其实就是一个成员函数,c++标准规定在函数调用中,必须保证参数被求植,具体怎么求值,就要看编译器的实现了。各个编译器的实现不一样,各个编译器就会有不同的结果。

猜你喜欢

转载自blog.csdn.net/qq_41017648/article/details/88898293