C 语言的语法问题

2015-05-27 20:52:10 +08:00
 bwangel
#include <stdio.h>
int main(int argc,char *argv[])
{
    int num;

    printf("%d %d\n",(num=100,1),num);

    return 0;
}

上面是代码,谁能给我解释一下那个(num=100,1)的值为什么是1,这条语句是个啥意思啊?

1240 次点击
所在节点    C
20 条回复
bwangel
2015-05-27 20:53:03 +08:00
程序的运行结果是
1 100
bwangel
2015-05-27 20:53:41 +08:00
感觉这个语句好神奇啊,哪位大牛能给俺科普科普,不胜感激!
moro
2015-05-27 20:55:32 +08:00
逗号表达式的返回值,应该是最后一个逗号的值。
wy315700
2015-05-27 20:55:51 +08:00
@bwangel
num=100,1
这句话首先 是给num赋值100
其次,这个是逗号分割的表达式, (a,b,c,d) 这个表达式的值 是d,
所以 (num=100,1) = 1
moro
2015-05-27 20:55:54 +08:00
其它语言也是一样的。
rrfeng
2015-05-27 20:56:53 +08:00
(num=100,1)

逗号运算符的优先级最低,作为一个整体,逗号表达式的值为最后一个表达式的值。
xdeng
2015-05-27 20:57:10 +08:00
3、4楼正解
bwangel
2015-05-27 21:06:06 +08:00
可不可以这样想,逗号的功能就是分割语句,相当与将多个语句整合成一条。然后它的结合性是从左到右。比如这条语句:

```c
num = 10, num = 20, num = 30
```

先执行num = 30 ,再执行num=20,最后执行num = 10

然后相当于变成了这个样子的代码(仅供参考,可能不是很严谨)
```c
10,20,30
```

然后再执行10,20,代码就变成了这个样子
```c
20,30
```

最后执行20,30这条语句,然后整个表达式的值就是30了?

各位看官,我分析的对不?
bwangel
2015-05-27 21:06:36 +08:00
额,为啥回复就不支持markdown。。。。。
theFool
2015-05-27 21:22:14 +08:00
@bwangel 不对。 num应该是==30. 照你的说法num==10了。
msg7086
2015-05-27 21:25:25 +08:00
并非是分割语句,而是分割表达式。

a = b 是赋值表达式
a = b; 是赋值语句
wy315700
2015-05-27 21:27:39 +08:00
@bwangel
逗号表达式是C的一种表达式

http://en.wikipedia.org/wiki/Comma_operator
bwangel
2015-05-27 21:37:01 +08:00
@msg7086 ,恩,确实是,我的表达有误!
bwangel
2015-05-27 21:40:11 +08:00
@theFool ,不是很理解你想说的意思,意思是我分析的那个num赋值顺序(30,20,10)不对,还是说我那个=不对,应该写成==
theFool
2015-05-27 21:43:15 +08:00
@bwangel 分析不对。照你的说法先执行num = 30 ,再执行num=20,最后执行num = 10 ,那num最后应该是等于10的。
qiuyi116
2015-05-27 22:49:29 +08:00
(num=100, 1)整体是一个逗号表达式,它的值是最后一个逗号后的值,即1;而逗号表达式的前面一个表达式是个赋值表达式,使得num的值为100。所以输出的值为1,100.
Maxi
2015-05-30 21:54:58 +08:00
优先级问题 ,逗号运算符级别最低 。所以先 100先给赋值用, 再计算逗号表达式的值. 如果num = (100, 1) 则是先计算逗号表达式的值。
FrankHB
2015-06-06 14:35:52 +08:00
@bwangel 逗号的功能不一定是“分隔语句”。
首先你得了解,C的语法中逗号并不都是一回事。有些逗号只是标点而不是操作符,如函数调用的postfix-expreesion中的分隔参数的逗号;而逗号表达式里的逗号操作符是另一回事。
最重要的影响语义的差异之一是,前者不限定求值顺序,而后者会插入一个sequence point。这里没有这个坑,但不知道迟早被坑。
语句之间是有sequence point的。从这个意义上来看,逗号操作符可以认为是在“分隔语句”。虽然实际上更像是个应付语句可用性缺陷设计的workaround(嘛,while条件里塞不进语句咋办……用逗号擦屁股吧)。而其它逗号,就显然不是这个意思。
printf("%d %d\n",(num=100,1),num);这坨里面,本来分号之前按postfix-expression来看,里面的逗号是argument-expression-list的组成部分——用于分隔作为参数assignment-expression的硬编码的分隔符而不是逗号操作符,但这里硬加了个括号,而作为argument的assignment-expression当然没法包括没配对的括号,语法分析就只能把(num=100,1)当作整个assignment-expression,然后继续规约:conditional-expression→...→primary-expression→( expression )→expression , assignment-expression——这里面的逗号就是逗号操作符了。
这里的要点是语法规则决定了assignment-expression的逗号不会被作为操作符,而加上括号以后括号里面的东西可以不是assignment-expression而是允许包含逗号操作符的一般expression,因此加上括号以后含义就变了。
wlee1991
2015-08-17 09:26:25 +08:00
@FrankHB 有没有英文出处 可以贴出来吗
wlee1991
2015-08-17 10:34:56 +08:00
c 语言提供一种特殊的运算符,逗号运算符,优先级别最低,它将两式联接起来,如:( 3+5,6+8 )称为逗号表达式,其求解过程先表达式 1 ,后表达式 2 ,整个表达式值是表达式 2 的值。
如:(3+5, 6+8 )的值是 14 ,(a=3*5, a*4 )的值是 60 ,原因在于赋值运算符优先级高于逗号运算符。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/194221

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX