主题:[讨论]自增 左值
cxxcomp
[专家分:2370] 发布于 2011-05-23 15:14:00
[code=c]
#include <stdio.h>
int main(int ac, char **av, char **ev)
{
int a = 5, b = 6;
++a = 10;
b++ = 10;
printf("%d\n", a);
}
[/code]
无意碰到一个小问题,写了段代码试了试,发现gcc编译器提示了第4,第5为无效的左值。 而icl居然编译通过了一个。[em17]
回复列表 (共10个回复)
沙发
windy0will [专家分:2300] 发布于 2011-05-23 21:32:00
++a = 10; b++ = 10 的语句 以及 a ^= b ^= a ^= b 一样, 都是不符合C标准的,
很显然,++a b++是不应该做左值,自增的时候有一次副作用,做左值(赋值语句)又一次副作用。
不过 标准有可能没有明确规定++a b++不能做左值,不然的话,icl不可能通过编译。
个人比较赞成gcc的这一做法,不然++a = 10以后,a 是10呢,还是 11呢?
板凳
cxxcomp [专家分:2370] 发布于 2011-05-23 22:42:00
gcc 、icl对这两个赋值表达式的汇编码确实不一样。按说,对于++a, b++编译器应该生成了一个变量的拷贝,完成除++运算之外的运算(前)后,在进行自加或自减。所以,从这个地方说,++a = 10, 实际的解释应该是把常量10赋给了一个常量数值(当然是右值,而绝不该是左值),然后常量自加(或反之,先自加,在赋值),所以,不应该编译通过。所以,icl能过一个,我有点意外。 从这点说,我确实稍微支持gcc/g++。
3 楼
雪光风剑 [专家分:27190] 发布于 2011-05-24 06:45:00
我觉得把自增的两个动作中的“引用”(是引用的动作,不是修饰符&)加以强调的话,那么即使标准没有明确提及,让自增作为左值也是不当的行为。当我们引用一个变量,其实我们实际上想往程序里面代入这个变量里此刻的状态,而不是改变其状态,因此自增作为左值我个人认为即使标准里没有提到,也不应该可以通过编译。
4 楼
cgl_lgs [专家分:21040] 发布于 2011-05-24 07:55:00
这就看编译器咋认为自增的返回值是常量还是变量。
5 楼
fragileeye [专家分:1990] 发布于 2011-05-24 09:05:00
[quote]++a = 10; b++ = 10 的语句 以及 a ^= b ^= a ^= b 一样, 都是不符合C标准的,
很显然,++a b++是不应该做左值,自增的时候有一次副作用,做左值(赋值语句)又一次副作用。
不过 标准有可能没有明确规定++a b++不能做左值,不然的话,icl不可能通过编译。
个人比较赞成gcc的这一做法,不然++a = 10以后,a 是10呢,还是 11呢?[/quote]
恩,说的是对得,++a和b++确实不应该作为左值,不过b++作为左值时编译通过也正如lz的解释,
6 楼
cgl_lgs [专家分:21040] 发布于 2011-05-24 22:30:00
[quote]++a = 10; b++ = 10 的语句 以及 a ^= b ^= a ^= b 一样, 都是不符合C标准的,
很显然,++a b++是不应该做左值,自增的时候有一次副作用,做左值(赋值语句)又一次副作用。
不过 标准有可能没有明确规定++a b++不能做左值,不然的话,icl不可能通过编译。
个人比较赞成gcc的这一做法,不然++a = 10以后,a 是10呢,还是 11呢?[/quote]
表达式不应做为左值,因为毫无意义(除非有特殊需要)。而a^=b^=a^=b却是合法的喔:)他只是相当于连等而已:)
7 楼
windy0will [专家分:2300] 发布于 2011-05-24 23:01:00
a^=b^=a^=b呵呵,我也觉得这个式子不会有歧义,但它确实违反了一点:两序列点之间一个确定的变量最多只能有一次副作用。而上面的a,b都有两次,好想标准有说,一次以上的副作用都叫未定义行为。不过,很有可能我记错了。
8 楼
cxxcomp [专家分:2370] 发布于 2011-05-25 01:18:00
刚翻了两眼侯世达的《哥德尔、埃舍尔、巴赫——集异璧之大成 》后,无意看到cgl_lgs同学的名字,发现如果把后面的"小S"也改为C的话,cgl_lgc,就呈现回文结构了。呵
9 楼
cgl_lgs [专家分:21040] 发布于 2011-05-25 22:43:00
[quote]刚翻了两眼侯世达的《哥德尔、埃舍尔、巴赫——集异璧之大成 》后,无意看到cgl_lgs同学的名字,发现如果把后面的"小S"也改为C的话,cgl_lgc,就呈现回文结构了。呵[/quote]
嘿嘿,改了就不是我的名字了:)
10 楼
cgl_lgs [专家分:21040] 发布于 2011-05-25 22:45:00
[quote]a^=b^=a^=b呵呵,我也觉得这个式子不会有歧义,但它确实违反了一点:两序列点之间一个确定的变量最多只能有一次副作用。而上面的a,b都有两次,好想标准有说,一次以上的副作用都叫未定义行为。不过,很有可能我记错了。[/quote]
这指的是在序列中,或是说形如参数列表这样的东西中。
而这个表达式则是遵循着右结合的连等式的:)
我来回复