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语言辨析------深入理解格式字符的用法

相关推荐
立志成为大牛的小牛1 分钟前
数据结构——十七、线索二叉树找前驱与后继(王道408)
数据结构·笔记·学习·程序人生·考研·算法
星空下的曙光3 分钟前
Node.js crypto模块所有 API 详解 + 常用 API + 使用场景
算法·node.js·哈希算法
Algo-hx4 分钟前
数据结构入门 (七):从“链接”到“分支” —— 初探树与二叉树
数据结构
小贾要学习1 小时前
【数据结构】C++实现红黑树
数据结构·c++
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
qiuiuiu4132 小时前
正点原子RK3568学习日志-编译第一个驱动程序helloworld
linux·c语言·开发语言·单片机
爱吃橘的橘猫2 小时前
嵌入式系统与嵌入式 C 语言(2)
c语言·算法·嵌入式
235162 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
weixin_307779133 小时前
使用Python高效读取ZIP压缩文件中的UTF-8 JSON数据到Pandas和PySpark DataFrame
开发语言·python·算法·自动化·json
柳安忆3 小时前
【论文阅读】Sparks of Science
算法