为什么这个逗号的使用在表达式中起作用但在声明中失败?

Mah*_*aha 5 c declaration comma-operator

来自高级OOP语言C#和Java,最近开始在C中摸不着头脑.我觉得C有点奇怪,就像有人觉得JS一样.所以想澄清如下:

下面给出了错误,这看起来很直观,因为即使在OOP语言中它看起来也是不正确的语法

int i=0,1,2;  

/*
Error : expected identifier or ‘(’ before numeric constant
 int i = 0, 1, 2;
            ^
*/
Run Code Online (Sandbox Code Playgroud)

但是下面的工作令人惊讶:

int i;
i = 0,1,2;    //works
Run Code Online (Sandbox Code Playgroud)

为什么会这样?保持这种行为或仅仅是一些解析技术问题是否有意义?

Yu *_*Hao 9

i = 0,1,2; 
Run Code Online (Sandbox Code Playgroud)

这是赋值,相当于:

(i = 0), 1, 2;
Run Code Online (Sandbox Code Playgroud)

逗号运算符(具有最低优先级)从左到右计算所有操作数,首先是赋值i = 0,然后是表达式1,2并将结果抛出.

第二个例子

int i=0,1,2;  
Run Code Online (Sandbox Code Playgroud)

是初始化.将其与合法初始化进行比较int i = 0, j = 0;.

它适用于您使用:

int i=(0,1,2); 
Run Code Online (Sandbox Code Playgroud)


Sha*_*our 7

这实际上是一个棘手的问题,因为它依赖于复杂的C语法的细节.理解它的最佳来源是草案标准,我们可以使用Annex A 语法语法摘要作为参考.

基本思路是:

int i=0,1,2; 
Run Code Online (Sandbox Code Playgroud)

是一份声明并且:

i = 0,1,2; 
Run Code Online (Sandbox Code Playgroud)

是一种表达.

在一个表达式中,我们可以使用逗号运算符来评估左侧(通常用于副作用),抛弃结果然后评估右侧等...

在声明中,逗号是语法分隔符而不是逗号运算符.在,中隔离声明符和自12是不是在这个声明的上下文说明符是不正确的语法:

 int i=0,1,2;
        ^^^^
Run Code Online (Sandbox Code Playgroud)

C99标准的相关语法如下:

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator   <--- here comma is just a seperator
init-declarator:
    declarator
    declarator = initializer
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,,中隔离初始化声明符它可以是一个声明符声明符=初始化既不1也不2声明中使用,所以我们有不正确的语法.

这是一文不值,一个初始化可以是一个赋值表达式,但这种表达不为我们提供了一个光秃秃的路径逗号操作符,虽然我们可以用逗号操作结束()(通过基本表达式),但是这不会像分隔符.

对于表达式,来自部分的相关语法6.5.17是:

expression:
    assignment-expression
    expression , assignment-expression
Run Code Online (Sandbox Code Playgroud)

逗号运算符的描述如下:

逗号运算符的左操作数被计算为void表达式; 评估后有一个序列点.然后评估右操作数; 结果有它的类型和价值.[...]

注意逗号运算符具有以下表达式的最低优先级:

i = 0,1,2; 
Run Code Online (Sandbox Code Playgroud)

相当于:

(i = 0),1,2; 
Run Code Online (Sandbox Code Playgroud)

因此i将获得价值,0并且进一步评估的结果将被丢弃.