c语言编译器指的是什么,c语言编译器是如何解析表达是式的?望高手指教下

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

C99

i++ 值为 i,再让 i 自增 1;右值

++i 让 i 自增 1,用增 1 后的值作为表达式的值;右值

因为 i=i++; 在分号前没有序列点(序列点:该点之前对变量的各种影响应该完成,而后面的影响仍未发生。序列点能保证 ++i 等增 1 效果确实已经发生),所以 i 增 1 的效果不确定发生在何时。标准只规定发生在前一个序列点之后,后一个序列点之前。前面的 i 可能是增 1 后的 i,也可能是未增 1 后的。语句执行后 i 的值可能为 i 原值,也可能是原值+1,未定义。

Example 里提到过,表达式中何时增 1 是编译器相关的(只有 ; 产生了序列点,而相邻两序列点间有两次或以上的赋值,就是未定义),标准未定义行为。第 67 页备注里提到过,形如 i = ++i+ 1; a[i++] = i; 这样的语句都是标准未定义的。

C++2003

i++ 值为 i,再让 i 自增 1;右值,不可取址,优先级很高

++i 让 i 自增 1,用增 1 后的值作为表达式的值;左值,可取址(不满),优先级较高(比后缀自增运算符低)

对于 built-in 的类型,效果同 C99

对于非 built-in 类型,= ++ 是重载的,由于重载运算符实际上是函数,就会调用 operator= 函数,因为标准规定函数调用前和退出后后各有一个序列点。于是 i 的值将是调用 operator++ 函数后的值,并非未定义行为

★★★★★

对于 i=j=0; 对于 C99 标准并非未定义,而 C++2003 却是未定义的。关键在于,赋值运算符返回的结果,在 C99 中是右值,在 C++2003 中则是左值,作为赋值运算符的右操作数,左值需要转换为右值,导致对变量进行读取。然而,标准规定两个相邻序列点间的读取,不能是发生在修改之后的读取。i=j,这个j将进行重新读取,未定义。这样一来,C99 很多合法代码就成了未定义的,有很多人不满。

★★★★★

另外,

F(++i) //F 函数内部会引用 i

(a+=2) && (a+=1)

++a || --a

++a ? 2 : 1

a++, a

1。对于 built-in 类型

并非未定义行为,因为根据 C99 标准,&& || ?; , 左操作数求值有序列点,对变量的影响全部完成,后面如果引用到该变量,将是影响发生后的变量,并非未定义。C99:函数各参数全部求值后有一个序列点(库函数(非普通函数调用后也会有序列点);C++2003:函数调用前、退出后各有一个序列点。两种标准虽有差异,但都能保证 ++ 在对 i 产生影响后才会进入函数体

引用 C99 标准对逗号运算符的说明,译成中文:“逗号运算符的左操作数作为无类型表达式进行运算,它的运算有个顺序。然后右操作数进行运算。整个表达式的结果的类型和值都是右操作数的类型和值。如果尝试修改逗号表达式的结果,或者在下一个序列点存取(access)它,产生的行为是未定义的。”

2。对于非 built-in 类型,重载了 &&、|| 或 ,

显然 C语言 不支持重载,该情况仅在 C++ 中发生。因为重载后就成了函数,&& || , 不会产生短路语义,只在进出函数体时有序列点。所以,(a+=2) && (a+=1) 将是未定义的

★★★★★

i++ + ++i 这样的表达式就分析到这儿了,如果你们的卷子上出现这种题,你应该向老师指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值