C语言辨析——int a=5;为什么++a=1能编译通过而a++=1不行呢?

1. 问题

有人问:int a=5; 为什么++a=1能编译通过a++=1编译错误呢?

解释:不管是++a=1还是a++=1在C编译环境下都无法编译通过,但在C++中,++a=1可以编译通过,而a++=1无法编译通过,这也是C和C++的一个不同。因此,这是一个关于C++的问题

2. 分析

不管是C还是C++,语句a++=1;的行为是未定义的,因为它违反了"如果在没有序列点表达式中多次修改 同一标量的行为是未定义行为"。

对于++a=1,等效于(a+=1)=1,对于C而已 (a+=1)不是左值,因此不能将1赋值给++a。因此,在C中编译通不过,给出的错误信息是:

Error\] lvalue required as left operand of assignment 但对于C++而言,表达式++a=1是正确的,因为++a在C++ 标准中是[左值](http://mp.weixin.qq.com/s?__biz=MzIyNDQyMzQ5Ng==&mid=2247492482&idx=5&sn=ff87ab834885cdf557d0ca1dde5eeb99&chksm=e80d98a5df7a11b37ad62ec0da5593f69465131ec5ce7a029c1c1894f187c06f252e4c8d6619&scene=21#wechat_redirect "左值"),因此,语句++a=1;在C++中是正确的语句。虽然该语句在C++中是正确,但不建议这样写。 表达式a++=1在C或C++中都是错误的,因为它试图两次修改同一个对象,这是不允许的。讨论这个话题就像讨论一个错误的时钟在一个小时后的时间是多少而已。 注:**左值** **(Ivalue)** 这个词最初源自赋值表达式E1=E2,其中左操作数E1必须是(**可修改的** )表达式。[对象(object)](http://mp.weixin.qq.com/s?__biz=MzIyNDQyMzQ5Ng==&mid=2247491525&idx=1&sn=fc627b346fcc183b506d144030f12fa9&chksm=e80e64e2df79edf4cbaba847dcb9cc890d7dca0a5bdea74eece80bcc1e6442030394ea267dbf&scene=21#wechat_redirect "对象(object)")是一块内存区域,可以读取它的值或者向它存储数据。一般将左值视为对象的"**定位值** (locator value)",**即左值是一种表达式,可以通过它读取或修改它所引用的对象。**例如,表达式a和b都是左值,但表达式3和b+3都不是左值。再如,若一元表达式E是一个指向对象的指针,则\*E是一个左值,表示E指向的对象。 **C99** 对**左值的定义是** :左值是具有[对象](http://mp.weixin.qq.com/s?__biz=MzIyNDQyMzQ5Ng==&mid=2247491525&idx=1&sn=fc627b346fcc183b506d144030f12fa9&chksm=e80e64e2df79edf4cbaba847dcb9cc890d7dca0a5bdea74eece80bcc1e6442030394ea267dbf&scene=21#wechat_redirect "对象")**类型** 或**非void的不完整类型的表达式** ,如果左值在求值时没有指定**[对象](http://mp.weixin.qq.com/s?__biz=MzIyNDQyMzQ5Ng==&mid=2247491503&idx=1&sn=363b8f308acd6dbd5a80ef0e4ccb2dea&chksm=e80e6488df79ed9e3e7944441ca89cd087d9e2fa5a6db56100c19cba8b6a054eeaaa50f69aeb&scene=21#wechat_redirect "对象")**,则其行为是未定义的。 **C11起** 对**左值的定义是** :左值是一个表达式,该表达式潜在地指示一个**对象** ,且该**对象类型不是void**,如果左值在求值时没有指定对象,则其行为是未定义的。 **3. 进一步分析** 在C标准中,由自增和自减运算符构成的表达式是右值(在C标准中,有时把右值(rvalue)描述为表达式的值),但在C++中,前缀形式的运算符构成的表达式是左值。因此,在C语言中,即a++和++a不是左值而是右值,因此无法为它们赋值。而在C++ 中++a是左值,因此可以给++a赋值,这就是为什么在C++中语句++a=1; 能编译通过的原因。 注:在C标准中,赋值和复合赋值运算符构成的表达式是右值,但在C++中是左值。例如 表达式(a=3\*4)=5+6在C中是错误的,但在C++ 中是正确的。对于表达式a=3\*4来说,在C中不是左值,因此不能将表达式5+6赋值给它,但在C++ 中它是左值,因此,可以将5+6赋值给(a=3\*4)。 **4. 经验** 如果一个变量出现在一个函数的多个参数中,不要对该变量使用递增或递减运算符。 如果一个变量多次出现在一个表达式中,不要对该变量使用递增或递减运算符。 C语言学习50 C语言学习 · 目录 上一篇C 语言基本概念----序列点下一篇C语言辨析------深入理解格式字符的用法

相关推荐
IT猿手3 小时前
基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
神经网络·算法·matlab·人机交互·无人机·强化学习·无人机三维路径规划
czy87874754 小时前
C语言主要标准版本的演进与核心区别的对比分析
c语言
巨龙之路5 小时前
C语言中的assert
c语言·开发语言
万能程序员-传康Kk6 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球6 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll7788116 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~6 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法
爱coding的橙子7 小时前
每日算法刷题Day2 5.10:leetcode数组1道题3种解法,用时40min
算法·leetcode
Akiiiira7 小时前
【数据结构】栈
数据结构
程序媛小盐7 小时前
贪心算法:最小生成树
算法·贪心算法·图论