关于逗号表达式的问题

程序如下
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 1;
int b = 2;
int c = 3;
c = a + b - (a = b, b = c);
printf('a = %d\n', a);
printf('b = %d\n', b);
printf('c = %d\n', c);
return 0;
}
输出结果:a=2 b=3 c=1
以下是解释:大家都知道,逗号表达式的计算顺序是从左向右,逗号左边的表达式被舍弃,表达式结果的类型和数值是逗号右边表达式的类型和数值。那么结果为什么不是c=1呢?是这样的,程序执行过程中,先将b的值赋给a,再把a和c的值相加,结果放在寄存器ecx中,然后把c的值赋给b,最后再把ecx与b的值相减,结果赋给c。原来程序运行时先把逗号左边表达式的值计算出来丢弃掉,然后再做其他的运算。
问:为什么先算小括号里边左边的,再跳出计算前面的加法,再计算小括号里边的右边的表达式,在算减法。
对不起,由于程序是我更改后的,忘记更改解释了,源程序是 c = a + C - (a = b, b = c);,结果是2,3,2

首先,你的题目错了吧?printf("x=%d,y=%d",x,x);应该是printf("x=%d,y=%d",x,y);吧?
结果应该是x=4,y=11
解释如下:
逗号运算符优先级最低。第一个虽然是顺序求值,但只把3*5的值赋给啊;第二个括号优先级高于逗号,所以a=10
下面是逗号运算符的讲解:
C语言提供一种特殊的运算符——逗号运算符。用它将两个表达式连接起来。如:
3+5,6+8
称为逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为
表达式1,表达式2
逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。例如,上面的逗号表达式“3+5,6+8”的值为14。又如,逗号表达式
a=3*5,a*4
对此表达式的求解,读者可能会有两种不同的理解:一种认为“3*5,a*4”
是一个逗号表达式,先求出此逗号表达式的值,
如果a的原值为3,则逗号表达式的值为12,将12赋给a,
因此最后a的值为12。另一种认为:“a=3*5”是一个赋值表达式”,“a*4”是另一个表达式,二者用逗号相连,构成一个逗号表达式。这两者哪一个对呢?赋值运算符的优先级别高于逗号运算符,
因此应先求解a=3*5(也就是把“a=3*5”作为一个表达式)。经计算和赋值后得到a的值为15,然后求解a*4,得60。整个逗号表达式的值为60。
一个逗号表达式又可以与另一个表达式组成一个新的逗号表达式,如(a=3*5,a*4),a+5
先计算出a的值等于15,再进行a*4的运算得60(但a值未变,仍为15),再进行a+5得20,即整个表达式的值为20。
逗号表达式的一般形式可以扩展为
表达式1,表达式2,表达式3……表达式n
它的值为表达式n的值。
逗号运算符是所有运算符中级别最低的。因此,下面两个表达式的作用是不同的:

x=(a=3,6*3)

x=a=3,6*a
第①个是一个赋值表达式,将一个逗号表达式的值赋给x,x的值等于18。第②个是逗号表达式,它包括一个赋值表达式和一个算术表达式,x的值为3。
其实,逗号表达式无非是把若干个表达式“串联”起来。在许多情况下,使用逗号表达式的目的只是想分别得到各个表达式的值,而并非一定需要得到和使用整个逗号表达式的值,逗号表达式最常用于循环语句(for语句)中.
请注意并不是任何地方出现的逗号都是作为逗号运算符。例如函数参数也是用逗号来间隔的。如
printf("%d,%d,%d",a,b,c);
上一行中的“a,b,c”并不是一个逗号表达式,它是printf函数的3个参数,参数间用逗号间隔。
如果改写为
printf("%d,%d,%d",(a,b,c),b,c);
则“(a,b,c)”是一个逗号表达式,它的值等于c的值。括弧内的逗号不是参数间的分隔符而是逗号运算符。括弧中的内容是一个整体,作为printf函数的一个参数。
C语言表达能力强,其中一个重要方面就在于它的表达式类型丰富,运算符功能强,因而c使用灵活,适应性强
温馨提示:答案为网友推荐,仅供参考
第1个回答  2020-01-02
x=4,y=11;
第三行和第四行都是逗号表达式,但是有区别;
第三行中x=a+1是逗号表达式的第一个式子,b+6是第二个式子;
所以x=a+1=4;
第四行中的a+1和b+6组成逗号表达式,逗号表达式的值付给y,所以b+6等于11付给y。
第2个回答  2012-05-02
首先, 你这段解释有问题。
I. "结果为什么不是c=1呢" 这是想证明结果是1还是不是1?前面说了输出是1,这里又说不是?
II. 先将b的值赋给a,再把a和c的值相加 -> 如果c没赋值给b,为何要 a + c? 写错了吧,想说再把a和b值相加?

其次, 这里加法减法连接的子表达式的求值次序是没有定义的,不能假定是从左向右!所以,不要写这样结果不确定的代码。

根据C语言标准C98只有很少的表达式存在“顺序点”, 见6.5节:
3 The grouping of operators and operands is indicated by the syntax.71) Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation
of subexpressions and the order in which side effects take place are both unspecified.

你问的这段解释,可以理解为特定编译器下的处理方式,同C语言无关!如果不是研究编译器,就不必考虑这个细节了。 如果这段解释的本意是说C语言就是这样处理表达式的,那么你可以认为它是错的!追问

对不起,由于程序是我更改后的,忘记更改解释了,源程序是 c = a + C - (a = b, b = c);,结果是2,3,2
谢谢你的回答,我们也才是编译器的问题.....

追答

那明白这段解释的意思了。它说的只是一种编译器下的处理方式。
可以确定是编译器的问题,同样代码gcc下结果
a = 2
b = 3
c = 1
vs2010下结果:
a = 2
b = 3
c = 2

看来这段解释适用于gcc下,不适用于vs2010下。对于gcc下,这段解释是否合理呢?
让我们看下gcc汇编代码:
movl $1, 20(%esp) #a = 1
movl $2, 24(%esp) #b = 2
movl $3, 28(%esp) #c = 3
movl 24(%esp), %eax #b -> eax
movl %eax, 20(%esp) #a = b(eax) => a = b = 2 果然,先算括号内左边的a=b
movl 24(%esp), %eax #b -> eax
movl 20(%esp), %edx #a(2) -> edx
addl %eax, %edx #a + b -> edx (2+2=4) 然后算 a + b
movl 28(%esp), %eax #c -> eax
movl %eax, 24(%esp) #b = c => b = 3 接着算括号内逗号右边b = c
movl %edx, %eax #edx(a+b) -> eax => eax = 4
subl 24(%esp), %eax #eax - b(3) => eax = 4 - 3 = 1 最后减去c
movl %eax, 28(%esp) #c = eax = 1

可见gcc对这段代码的处理方式对c = a + b - (a = b, b = c)的处理同解释完全相符!

vs2010的处理方式可以猜测如下:
先算括号内
a = b = 2
然后b = c = 3
这时继续算a + b = 2+ 3 = 5
最后-c, 得 5 - 3 = 2

本回答被提问者采纳
第3个回答  2019-01-27
我想可能是这样:X=4,Y=11
逗号好像是最低级的,那x=a+1=4再算b+6=11没存结果。
y=b+6=11逗号表达式以最后式结果为整式结果。
参考,参考,不一定对。
第4个回答  2012-05-02
这个需要复习一下~追问

那就复习一下给我解释一下吧

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网