首页 > 其他分享 >自增符号a++与++a遇到的问题

自增符号a++与++a遇到的问题

时间:2023-04-04 23:00:24浏览次数:34  
标签:自增 符号 ++ 代码 先算 -- int printf

在贴吧看到有吧友问Java和C对于同一代码的运行得到不同的结果,代码如下:

// 代码1
int a;
a= ++a + a++;
printf("a=%d",a);
输出为:a=3

我在DevC++5.7.1上测试了这段代码,并尝试了一个修改:

// 代码2
int a;
a= a++ + ++a;
printf("a=%d",a);
输出为:a=2

竟然出现了不同!
正在学习C语言,所以调试了一下,保留后缀形式,尝试以下代码:

// 代码3
int a;
a= ++a + a;
printf("a=%d",a);
输出为:a=2

这个很好理解,因为在“=”“++”“+”三个运算符中,优先级顺序是“++”“+”“=”;并且对于++a,它等价于以下代码:

// 代码4
int a=0;
a=a+1;
return a;

因此代码3中的赋值语句,应该是a=1+1
我又尝试了保留前缀形式,即以下代码:

// 代码5
int a;
a= a + a++;
printf("a=%d",a);
输出为:a=1

运算上同样有优先级顺序:先计算a++,它等价于以下代码:

// 代码6
int a=0;
return a;
a=a+1;

显然a++=0,然后计算a + a++,因为经过自增之后a=1,因此代码5中的赋值语句,应该是a=1+0
和前面差不多,但是得到了一些新东西。我原本将后缀的值的使用理解为“该语句执行完毕才更新值”,现在看来,在同一行内就已经更新了值,并且传递给了变量a


回过头去看代码2,很清楚,根据优先级顺序计算即可:
首先a++=0,但是a=1,在此基础上++a=2,因此代码2的赋值语句应该为:a=0+2
再回头看代码1,这就有问题了,因为按道理说,他的结果应该和代码2一样,但是不一样,我想要搞明白哪里的问题,可我理论知识不足,因此我需要试探一下:
试探什么地方?我怀疑a++自增之后,在求和时,使用了更新后的值,而不是原始值0
试探方法很简单,因为a++的优先级最高,可以仅保留a++自增的效果(也就是在声明时int a=1;),不使用更新后的值(也就是把a++替换为0)。

// 代码7
int a=1;
a= ++a + 0;
printf("a=%d",a);
输出为:a=2

这是显而易见的,但这也是符合预期的,只不过把a++的动作进行了手动设置。
再试探一下,将0改为a,看看是否符合猜想:

// 代码8
int a=1;
a= ++a + 1;
printf("a=%d",a);
输出为:a=3

符合猜想。那么尝试性地做一个检验:

// 代码9
int a=-1;
a= --a + (-1);
printf("a=%d",a);
输出为:a=-3

运行下面的代码,的确输出了-3

// 代码9
int a=0;
a= --a + a--;
printf("a=%d",a);
输出为:a=-3

说明存在这样的问题


我于是把a++``++a``a--``--a进行组合,看看是否存在类似的异常,得到以下结果:

// a= a++ + ++a;  // 0+2=2,前者先算,后者后算,前者用旧值,后者用新值 --正常
// a= ++a + a++;  // 2+1=3,后者先算,前者后算,全用新值 --异常
// a= a-- + --a;  // 0+(-2)=-2,前者先算,后者后算,前者用旧值,后者用新值 --正常
// a= --a + a--;  // -2+(-1)=-3,后者先算,前者后算,全用新值 --异常
// a= --a + a++;  // -1+0=-1,前者先算,后者后算 ,全用新值 --异常
// a= a++ + --a;  // 0+0=0,前者先算,后者后算,前者用旧值,后者用新值 --正常
// a= a-- + ++a;  // 0+0=0,前者先算,后者后算,前者用旧值,后者用新值  --正常
// a= ++a + a--;  // 1+0=1,前者先算,后者后算,全用新值 --异常

我觉得手算可以用表格,比较方便,以a= ++a + a++;为例:

旧值 新值
高优先级 a++ 0 1
低优先级 ++a 1 2

运算顺序给定以后,只有4种可能的结果,因此很容易根据结果查看原因,结果输出是3,可以看出是a++1导致结果与预想的不同。


最后,按照书上的说法,采取这种写法可以加快运行速度,这才是使用它的原因,而不是因为写起来简单。因此,不想导致未知的错误,不想一点一点的排查,最好的办法就是将代码写得清晰易懂,而不是为了追求简洁把代码写得复杂无比,不止为了别人看得懂,更重要是为了自己检查时方便。
这种++--写得很复杂还是要看的,自己虽然不去写,但是还是有不少面试题会考,该会还是要会
至于这些异常出现的原因,我认为是编译器的锅,我没有能力解决问题,我只是把我可能遇到的问题进行了总结。

标签:自增,符号,++,代码,先算,--,int,printf
From: https://www.cnblogs.com/Hubugui/p/17287684.html

相关文章

  • C/C++编译过程
    1.预处理 将.c中的头文件、宏展开生成的文件是.i文件gcc-Ehello.c-ohello.i2.编译将预处理后的.i文件生成.s汇编文件gcc-Shello.i-ohello.s3.汇编将.s文件生成.o目标文件gcc-chello.s-ohello.o4.链接将.o文件链接成可执行文件gcc-chello.o-ohello......
  • 基础C++程序题的基础归纳Ⅲ
    基础C++程序题的基础归纳Ⅲ1、去重排序题目描述ZN想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大......
  • 为虚幻引擎C++项目设置Visual Studio开发环境 | 虚幻引擎5.1文档 (unrealengine.com)
    设置VisualStudio设置VisualStudio以使用虚幻引擎的提示、技巧和技术Beginner本页面的内容版本兼容性新安装VisualStudio时的选项推荐设置虚幻引擎(简称UE) 能与 VisualStudio(简称VS) 完美结合,使你能够快速、简单地改写项目代码,并能即刻查......
  • C++多态
    多态是C++面向对象最主要的特性之一,多态即多种形态,多个不同对象对同一事物会产生不同状态多态的实现1.虚函数重写实现多态的必要条件是虚函数,父类中有虚函数,子类重写虚函数,实现同一对象的不同表达方式。2.多态的要求 (1、被调用的函数必须是虚函数,子类对父类的虚函......
  • VsCode安装和配置c/c++环境
    vscode是代码编译器,同时它提供了许多插件,可以帮助你方便的编写代码。通过配置vscode的开发环境,可以实现多种语言编译。总而言之,装了一个vscode就相当于装了多个IDE(集成开发环境)。后面,我们编写C语言代码就要依靠vscode了。一、下载vscode网址:VisualStudioCode-CodeEditing.......
  • C++实现AES加密
    参考https://zhuanlan.zhihu.com/p/567141666本人开发环境:vs2022,平台工具集vs2015(v140)要做到的如下图需要下载Cryptopp库https://github.com/weidai11/cryptopp打开默认工程,生成即可,选择cryptlib项目点击生成,产生头文件和lib文件实现代码:#include<Cryptopp/aes.h>#i......
  • Notepad++ 中,要匹配数字并将其换行
    在Notepad++中,要匹配数字并将其换行,您可以使用正则表达式。请按照以下步骤操作:打开Notepad++,然后打开要处理的文件。按Ctrl+H打开“查找与替换”对话框。在“查找”标签下,选择“正则表达式”选项。在“查找内容”框中输入以下正则表达式:(\d+)这个正则表达式将匹配一个或多......
  • 【C++学习笔记】关于const int* 、 int const * 、 int* const
    constint*、intconst*、int*const的关键点在于const与*的位置,而const与类型int的位置无关,可以随意调换,属于个人代码风格,不过建议写成constint*,方便直观。constint*与int*const的区别在于const修饰的是int*还是变量,其中constint*a修饰的是int*,表示这个......
  • c++vector怎么用
    ANSWERC++中的vector是一个能够存放任意类型的动态数组,能够增加和压缩数据,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。以下是使用vector的详细步骤和注意事项:头文件在使用vector时,需要包含vector头文件include初始化如果vector的元素类型是int,默认初始......
  • c++ 数字和string 类型的相互转换
    C++数字和string类型的相互转换数字转为string1.std::to_string()函数//Definedinheader<string>std::stringto_string(intvalue);//(sinceC++11)std::stringto_string(longvalue);//(sinceC++11)std::stringto_str......