5

Am from high level OOP languages C# and Java and recently started scratching my head in C. I feel C a bit weird as equally as one feels JS is. So want to clarify below:

Below gives error and that seems intuitive as it looks like incorrect syntax even in OOP languages

int i=0,1,2;  

/*
Error : expected identifier or ‘(’ before numeric constant
 int i = 0, 1, 2;
            ^
*/

However below works surprisingly:

int i;
i = 0,1,2;    //works

Why is this behavior? Is their any significance to keep such behavior or just some parsing technicalities?

4

3 回答 3

9
i = 0,1,2; 

这是赋值,相当于:

(i = 0), 1, 2;

逗号运算符(优先级最低)从左到右计算所有操作数,首先是赋值i = 0,然后是表达式,然后12结果丢弃。

第二个例子

int i=0,1,2;  

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

如果您使用它,它会起作用:

int i=(0,1,2); 
于 2014-10-22T10:50:14.350 回答
7

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

基本思想是:

int i=0,1,2; 

是一个声明,并且:

i = 0,1,2; 

是一个表达式。

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

在声明中,逗号是语法分隔符而不是逗号运算符。在声明的上下文中,,分隔声明符和 since12不是声明符,这是不正确的语法:

 int i=0,1,2;
        ^^^^

C99标准的相关语法如下:

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator   <--- here comma is just a seperator
init-declarator:
    declarator
    declarator = initializer

因此,在这种情况下,,分隔init-declarators既可以是声明符,也可以是声明符 = 初始化器1,也不是2声明,因此我们的语法不正确。

初始化器可以是赋值表达式是毫无价值的,但是这个表达式并没有给我们一个通向逗号运算符的路径,尽管我们最终可以在()通过主表达式)中得到一个逗号运算符,但这看起来不像一个分隔符。

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

expression:
    assignment-expression
    expression , assignment-expression

逗号操作符的描述如下:

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

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

i = 0,1,2; 

相当于:

(i = 0),1,2; 

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

于 2014-10-22T12:01:05.073 回答
0

1.

  int i, j;
  i = 3,0,1,2;
  printf("%d\n", i); => prints 3

2.

  i = 3,j =7;
  printf("%d, %d\n", i, j); => prints 3 and 7

i = 3,0,1,2;这个赋值3 to i,然后执行0, 1 and 2。检查我提到的第二个例子。

此外,Try i=3;0;1;2;This 不会报告任何错误。它只会执行(i=3), (0), (1) and (2).

于 2014-10-22T11:00:08.377 回答