C++中关于:单语句cout指针地址与指向的值的同时自增时,程序内部运算顺序探究
看不懂标题?没关系直接拿下面示例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:
还没来得及测就被吓傻了
赶紧百度+谷歌
搜到以下结果:点我查看原网址