++i 的结果

Could not find a package configuration file provided by “boost_signals“ gmapping/slam_gmapping/gmapping/CMakeLists.txt:14 (find_package)问题在14行,注释该行。,该语句的用以为告诉项目Boost库文件所在。 阅读详情

转自 Jack_WJQ 的博客: https://blog.youkuaiyun.com/qq_26377547/article/details/88670308

非计算机专业的老师讲到C/C++中,i=2时,(++i)+(++i)+(++i)+(++i)的计算结果的时候,给出的答案是19。我感到很困惑,按照正常的计算逻辑结果应该是18,于是我到菜鸟教程的在线编译器上面试了一下,得到的结果是18,后来又在Xcode上试了一次,得到的结果也是18,更换了ACM竞赛专用的codeblocks编译,结果是19。

贴出代码:

#include "stdio.h"
int main() {
    int i=2;
    int sum=(++i)+(++i)+(++i)+(++i);
    printf("%d\n", sum);
}

由此产生了一个疑问,是什么样的原因导致了这个差异?计算出19的计算逻辑又是怎样的?

感觉是编译器的问题,但这个编译器在数值计算上为什么会导致这个差异,希望大佬能解答一下这个问题产生的深层原理。
codeblocks编译结果
Xcode编译结果
菜鸟教程在线编译器编译结果
解答来自思否一位大佬,链接:https://segmentfault.com/q/1010000018570689
解答:

一.副作用(side effect)

表达式有两种功能:每个表达式都产生一个值( value ),同时可能包含副作用( side effect )。副作用是指改变了某些变量的值。如:

20         //这个表达式的值是20;它没有副作用,因为它没有改变任何变量的值。
x=5       // 这个表达式的值是5;它有一个副作用,因为它改变了变量x的值。
x=y++     // 这个表达示有两个副作用,因为改变了两个变量的值。
x=x++     // 这个表达式也有两个副作用,因为变量x的值发生了两次改变。

二.求值顺序点

表达式求值规则的核心在于 顺序点( sequence point ) [ C99 6.5 Expressions 条款2 ] [ C++03 5 Expressions 概述 条款4 ]。
顺序点的意思是在一系列步骤中的一个“结算”的点,语言要求这一时刻的求值和副作用全部完成,才能进入下面的部分。在C/C++中只有以下几种存在顺序点:

1)分号;

2)未重载的逗号运算符的左操作数赋值之后(即’,'处)

3)未重载的’||‘运算符的左操作数赋值之后(即’||'处);

4)未重载的’&&'运算符的左操作数赋值之后(即"&&"处);

5)三元运算符’? : ‘的左操作数赋值之后(即’?'处);

6)在函数所有参数赋值之后但在函数第一条语句执行之前;

7)在函数返回值已拷贝给调用者之后但在该函数之外的代码执行之前;

8)每个基类和成员初始化之后;

9)在每一个完整的变量声明处有一个顺序点,例如int i, j;中逗号和分号处分别有一个顺序点;

10)for循环控制条件中的两个分号处各有一个顺序点。

对于任意一个顺序点,它之前的所有副作用都已经完成,它之后的所有副作用都尚未发生。

在两个顺序点之间,子表达式求值和副作用的顺序是不同步的。如果代码的结果与求值和副作用发生顺序相关,称这样的代码有不确定的行为(unspecified behavior).而且,假如期间对一个内建类型执行一次以上的写操作,则是未定义行为.

任意两个顺序点之间的副作用的发生顺序都是未定义的.

如:

x=x++;

该表达式只有一个顺序点,在该顺序点之前有2个副作用,一个是自增,一个赋值,这两个副作用发生的顺序是未定义的,即自增运算和赋值运算哪一个先执行是没有被定义的(注意这个顺序跟运算符的优先级是无关的,注意理解运算符优先级的含义),这个执行次序交由编译器厂商去自行决定,因此对于不同的编译器可能会得出不同的结果。

#include <stdio.h>
#include <stdlib.h> 
int main(int argc, char*argv[])
{
    int i=0;
    int m=(++i)+(++i)+(++i)+(++i);
    printf("%d %d\n",m,i);
    system("pause");
    return 0;
}

对于上述代码:

在gcc编译器中运行得到的结果是 11 4

而在Visual Studio 2008中运行得到的结果是 16 4

因为对于

int i=0;
int m=(++i)+(++i)+(++i)+(++i);

在两个分号之间有5个副作用,这5个副作用与子表达式的求值顺序是未定义的,对于不同的编译器会得出不同的结果。

并且在这期间对i进行了不止一次的写操作,这也是一个未定义的行为,可能会引起任何后果。

还比如:

x[i]=i++;
printf("%d %d\n",i++,i++);
function(x,x++);

这些都是未定义的行为。

因此我们平时在写代码时,尽量不要写出这样风格不好的代码,因为它不仅会给程序带来不确定性,可能会引起任何后果(比如程序崩溃),而且对于代码的移植性来说是致命的打击。

比如:

x[i]=i++;

可以用这段代码去代替:

x[i]=i;
i++;

function(x,x++);-> function(x,x);x=x+1;
这样的代码才是风格良好的代码。

尽量保证,在两个相邻顺序点之间同一个变量不可以被修改两次以上或者同时有读取和修改,否则,就会产生未定义的行为。

MATLAB与图像处理(一):图像中结构张量的求法(Structure Tensor) 1.结构张量的作用:       能够区分图像中的平坦区域,边缘,角点; 2.图像中的结构张量的定义    1)是一个矩阵;    2)与图像的水平,垂直梯度有关,定义如下: 在MATLAB中,可以用如下语句求解:[Ix,Iy]=gradient(Image); 3)求出结构张量矩阵的行列式,和迹(矩阵对角线之和)   行列式:K=det(E);   迹:   阅读详情

相关推荐

Quest 3开发第一步:搞定Meta账号登录和Oculus软件连不上设备的那些坑(2024实测)

本文详细介绍了Quest 3开发初期的关键步骤,包括Meta账号注册、Oculus软件安装与设备连接等常见问题的解决方案。针对国内开发者遇到的邮箱限制、验证码接收等难题,提供了实用的应对策略,并分享了开发环境配置和常见问题排查技巧,帮助开发者快速搭建Quest 3开发环境。

weixin_30333885的博客 492

浅谈C/C++中的顺序点和副作用

顺序点这个知识点是我在想下面的代码时遇到的问题。可能看着很白痴,,但却有研究价值 int a=10,b=20; 然后分别运行下面的代码 1) a = a+b-(b=a); 2)a = (a+b) - (b=a); 3)a = -( (b=a)-(a+b)); 均没有实现a,b值的互换 于是从网上查找资料,找到了下面的文章,,转来给大家看看 转自:http://dev

GYTAnonymous的专栏 660

STM32CubeMX+FreeRTOS实战:3步搞定LED任务配置(附代码解析)

本文详细解析了如何使用STM32CubeMX图形化工具配置FreeRTOS实时操作系统,并创建LED闪烁任务。通过剖析MX_FREERTOS_Init()函数和CMSIS-RTOS封装层,深入理解任务创建、调度及osDelay()协作机制,帮助开发者从点击生成进阶到内核原理掌握,实现高效的多任务嵌入式开发。

weixin_29192141的博客 467

关于二级c中经常出现的数组排列算法的个人理解(y[j++]=x[i];x[i]=-1;)

关于二级c中经常出现的数组排列算法的个人理解 最近一直在复习c语言刷题准备考试,其中有一道程序题感觉很有意思,有些地方不是很明白,于是上网搜了一下也没有人说出些所以然来,自己研究了一下觉得对考试很有用,所以写在这里。 先看下代码: #include <stdlib.h> #include <stdio.h> #define N 10 double fun(double *x) { int i, j; double s, av, y[N]; s=0; f

weixin_50060428的博客 919

【Matlab】刃边法计算mtf

摘要:刃边法是一种测量光学系统调制传输函数(MTF)的常用方法。本文介绍了基于Matlab的MTF计算实现方案,包括图像灰度化、梯度计算、刀口方向选择、梯度投影等关键步骤,并给出了完整的代码实现。该方案可通过添加图像预处理、多方向计算、函数封装等方式进行扩展,提高MTF计算的准确性和实用性,适用于不同应用场景的光学系统性能评估需求。(148字)

unber的博客 389

Unity实战篇 | 教你怎样将Unity的启动Logo 设置成 自己制作的 帧动画

上一篇文章我们讲了怎样在不购买专业版的情况下自定义Unity的启动Logo。 那本篇文章就来介绍一下,怎样在去除默认Logo的前提下制作自己的启动动画!

努力前行,总会成为自己心中的那道光 6万+

【无标题】区分i++和++i

区分i++和++i

m0_70734407的博客 253

Winform利用动画控制实现各种特效

动画绘制控制类代码 using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Threading; using System.Windows.Forms; namespace Mengliao.CSharp.A14 { #region 动画类型枚举 // 本例为了简单起见没有使用见名知意的名称,如用于实际可将这些枚举成员更名

LilyCoder的博客 2501

C++第7次实验—函数复习

函数复习

大虾的世界 636

Transformer在BEV感知中的统治地位

Transformer在BEV感知中的统治地位 ,人工智能,计算机视觉,大模型,AI,本文围绕 Transformer 在 BEV 感知中的统治地位展开,介绍了 Transformer 的基础原理,如自注意力、多头注意力机制等,以及 BEV 感知的概念、任务与挑战。阐述了 Transformer 在 BEV 感知中的技术优势,包括全局建模、灵活特征融合和长距离依赖捕捉能力,还介绍了典型架构、代码示例及在自动驾驶目标检测等领域的应用案例。同时,评估了其性能,提及优化方法,并展望了与其他技术融合、端到端系统等…

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 20万+

Open3D 体素下采样【2026最新版】

体素滤波,博客长期更新,本文最近更新时间为:2026年4月11日。

点云侠的博客 37万+

Java自增变量;i++和++i的区别

简单来说 x = i ++; //先让x变成i的值1,再让i加1 x = ++i; //先让i加1, 再让x变成i的值1 案例解析 int i =1; int x=i++; System.out.println("i="+i); System.out.println("x="+x); 结果 i=2 x=1 int i =1; int x=++i; System.out.print

xul999的博客 437

【AI大模型应用开发】3.2 RAG实战 - RAG应用+UI实现加载本地文件并对话

前面我们实现了RAG基本流程,今天我们在此基础上给它加个UI界面,在浏览器打开,实现上传本地文件、解析,并用大模型实现与该文档的对话。也就是一个阉割版demo版的ChatPDF或知识库对话系统。

同学小张的博客 3053

好好分析下i++为什么i的结果没有变化

老生常谈的 i++和 ++i,今天从头到尾分析一遍。

fang0604631023的博客 484

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

i=i++结果分析

面试题中有时候会出现i=i++类似的情况,如下面代码所示: public class Test11 { public static void main(String[] args){ int count = 0; for(int i = 0; i < 10; i++){ count = count++; } System.out.println(count);//count=0 } } 在这一片段中,count使用for循环自加10次,但是最后输出的结果仍未0。 程序第一次

ding007drf的博客 665

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java中两个线程i++ 100次后i的结果

java中i++为什么不是原子操作?多线程下i++会出现什么状况

w55935的博客 1830

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

for循环中i++和++i的运行结果一样

通过以下例子可以看出for循环中i++和++i的运行结果一样 void main(void) { int r[8] ={49,38,65,97,76,13,27,49}; int i; for( i=0;i<=7;i++) { printf("r[%d]=%d\t",i,r[i]); printf("i=%d\n",i); } printf("i=%d\n",i); } 输出结果为: r[0]=49 i=0 r[1]=38 i=1 ...

weixin_51566949的博客 1256

左右赋值i++结果

int main() { int i=0; i=i++; i = i++; cout << i; } 结果为0 赋值运算从右到左,先计算i++,然后返回的是i变化之前的数值, public class Main { public static void main(String[] args) throws IOException { int i=0; i = i++; i = i++;

坚持的力量 331

synchronized下的 i+=2 和 i++ i++执行结果居然不一样

逛【博客园-博问】时发现了一段有意思的问题:问题链接:https://q.cnblogs.com/q/140032/这段代码是这样的:java 代码很简单(一开始我没看清楚问题,还建议楼主去学习下Java语法,尴尬的一批~~~)大家觉得这段代码会输出什么呢?没错就是死循环!!!有意思的地方来了,如果我把同步方法 evenIncrement() 改为下面这样:java 执行结果是退出了虚拟机!!!是不是很纳闷儿,要是不纳闷儿,就不用往下看了 >_...

weixin_45566993的博客 672

i++在两个线程执行100次,最终的结果是

i++语句只需要执行一条指令 但当有多个线程时,并不能保证多个线程i++,操作同一个i。因为还有寄存器的因素,多个cpu对应多个寄存器。 每次要先把i从内存复制到寄存器,然后++,然后再把i复制到内存中,这需要至少3步。 如此,假设两个线程的执行步骤如下: i++在两个线程中执行100次的时候,由于,对于多线程,线程共用一个内存,如果线程A在寄存器中执行了加一操作而没有写入内存,那么将会切入到另一个线程进行加一操作,在进程来回转换的过程中很可能导致原来内存中的值被覆盖,因此,此段代码执行的结果为:

usstmiracle的博客 3802

C语言 & Java 解析:当 i = i++ 后,结果究竟是什么?

前言: 之前有朋友跟我讨论过一个问题,他问在java中,i=1;i=i++;之后的结果时什么,我一开始认为是2,但当他说答案是1的时候,我不得不想一个合理的解释,我想,可能是因为临时变量,当i赋值给i后,自增更改了临时变量,所以i值并没有改变。当我在为我的解释表示满意时,他们说在c语言下的答案是2,好吧,我只能说是编译器的实现不同,当然这个答案太没说服力了,所以寻找答案的任务就开始了。 我先在《c++ primer》上看见这样的解释:“++i的效率要比i++的效率高,因为i++必须要有一个临时变量来

致力于C语言C++知识分享! 1191

java i++和++i的区别_面试官:你说你懂i++跟++i的区别,你看下这段代码的运行结果吧

原作者:程序员DMZ面试官:“说一说i++跟++i的区别”我:“i++是先把i的值拿出来使用,然后再对i+1,++i是先对i+1,然后再去使用i”面试官:“那你看看下面这段代码,运行结果是什么?”public static void main(String[] args) { int j = 0; for (int i = 0; i < 10; i++) { j =...

weixin_39679678的博客 76

三个线程每个执行50次i++的最终结果问题

摘要:多线程环境下执行i++操作可能导致结果不一致,因其非原子性。为保证三个线程各执行50次i++后结果为150,可采用以下方案:1)使用synchronized同步块,通过JVM内置锁实现线程安全;2)采用AtomicInteger原子类,基于CAS无锁机制;3)使用ReentrantLock锁,基于AQS框架管理线程同步。此外可通过CountDownLatch确保所有线程完成后读取结果。这些方法分别适用于不同并发场景,synchronized实现简单,AtomicInteger性能更高,Reentran

qq_46130027的博客 613

i = i++ 和 i = ++i 执行结果是什么?为什么?

i = i++ 和 i = ++i 执行结果是什么?为什么?

m0_46298655的博客 408

i++和++i的区别_面试官:你说你懂i++跟++i的区别,那你知道下面这段代码的运行结果吗?

面试官:“说一说i++跟++i的区别”我:“i++是先把i的值拿出来使用,然后再对i+1,++i是先对i+1,然后再去使用i”面试官:“那你看看下面这段代码,运行结果是什么?”public “以我多年的开发经验来看,它必然不会是10”面试官:我:“哈哈.....,开个玩笑,结果为0啦”面试官:“你能说说为什么吗?”我:“因为j++这个表达式每次返回的都是0,所以最终结果就是0”面试官:“小伙子不错...

weixin_39711441的博客 100

i++结果几何?

我观你骨骼清奇,面貌不凡,极其适合撸代码 下面有请第一位选手上场 第一关:请回答下面这道题的输出结果 public class JvmTest{ public static void main(String [] args){ int j = 0; for(int i = 0;i<10;i++){ j = (j++); } ...

小高同学 1536
上一篇: C++正则表达式(regex_match、regex_search与regex_replace)
下一篇: 春游2.0 | CCF考试 感想以及试题文件(我太菜了啊~~)
OneLine_
博客等级 码龄9年 48粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值