在初始化和声明语句中使用时逗号分隔符和逗号运算符的细微差别

Nuances of comma seperator and comma operator when used in initialization and declaration statements

在阅读了 Stack Overflow post(What does the comma operator , do?). Further, I was playing around with the , separator after reading this post: comma operator and comma seperator in c++ 上的几个答案后,我正在使用 , 运算符 。考虑一下以下两个代码片段:

代码 1

#include<stdio.h>
int main(void) 
{
  int a, b;      /* comma functions as a separator */
  a = 5, b=9;    /* NOT SURE how comma functions */
  printf("a = %d \n",a) , printf("b = %d \n",b);     /* comma functions as an operator */      
}

代码 2

#include<stdio.h>
int main(void) 
{
  int a, int b;   /* not allowed - compiler error ... NOT SURE how comma functions */
  a = 5, b=9;     /*NOT SURE how comma functions */
  printf("a = %d \n",a) , printf("b = %d \n",b);      /*comma functions as an operator */      
}

最上面的代码(代码 1)很好...并打印出 a=5b=9;但是,底部代码(代码 2)没有通过编译器并引用 int a, int b ; 行作为犯罪行为。


这两个代码片段中捆绑了很多问题,但我会列出我最关心的问题:

  1. 语句a=5,b=9;,是作为分隔符还是运算符?我在初始化语句中读到过,逗号用作分隔符。但是,鉴于我对逗号运算符的作用的理解,我觉得将此逗号归类为运算符也是有道理的。

  2. 为什么不允许int a, int b?如果允许逗号充当运算符,那么这肯定是有道理的,对吧? int a 将首先被评估,它会产生副作用,即用标识符 a 标记内存中的某个位置,然后 int b 将以类似的方式处理。因此,在这种情况下,编译器 似乎不想更改 , 的解释 (即它只想将其视为分隔符)。

如有解释,将不胜感激!谢谢~

C 中的声明定义(特别是)如

declaration:
    declaration-specifiers init-declarator-list ; 

术语 init-declarator-list 的定义类似于

init-declarator-list:
    init-declarator
    init-declarator-list , init-declarator

所以在这个声明的第一个程序中

int a, b;

没有逗号运算符。逗号用于分隔 init-declarator-list.

中的 init-declarators

此声明

a = 5, b=9; 

确实是一个逗号运算符表达式的语句。

此声明

printf("a = %d \n",a) , printf("b = %d \n",b);

也是逗号运算符表达式的语句。

第二个程序中的声明不正确

int a, int b; 

因为在 init-declarator-list.

内部使用了声明说明符 int

至于逗号则按照C标准(6.5.17 Comma operator)

2 The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value

您可以使用逗号运算符作为变量的初始值设定项,例如

int a = 10, b = 20;
int c = ( a++, b++, a + b );

变量 c 将由值 32 初始化。

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    int a = 10, b = 20;
    
    printf( "a = %d, b = %d\n", a, b );
    
    int c = ( a++, b++, a + b );

    printf( "a = %d, b = %d, c = %d\n", a, b, c );

    return 0;
}

它的输出是

a = 10, b = 20
a = 11, b = 21, c = 32
  1. In the statement a=5,b=9; is that , functioning as a separator or an operator?

这里的逗号是运算符。 C语法中:

  • 这是一个声明,它是一个expression-statement (C 2018 6.8)。
  • 它由一个表达式和一个; (6.8.3)组成。
  • 一个表达式可能是一个表达式后跟一个,然后是一个assignment-expression (6.5.17).
  • 逗号前的表达式也可能是assignment-expression (6.5.17).

所以a=5,b=9;是“assignment-expression,assignment-expression;”.

注意a=5不是“初始化语句”; C语法中没有这样的东西。这是一个assignment-expression。所以 a=5,b=9; 是两个赋值表达式,用逗号连接并以分号结束,形成一个语句。

  1. Why is int a, int b not allowed?

在C语法中:

  • 这是一个声明 (6.7)。
  • 它由 declaration-specifiers 后跟 init-declarator-list 后跟 ; ( 6.7).
  • declaration-specifiers可能是单个type-specifier(6.7)也就是int (6.7.2).
  • init-declarator-listinit-declarator的列表,用逗号分隔(6.7)。
  • 一个init-declarator可能是一个声明符 (6.7).
  • A 声明符 可能是一个标识符,如 ab (6.7.6)。

所以 int a, b; 是一个有效的声明。 C 语法中没有规定任何由逗号分隔的声明列表;语法中没有任何内容可以扩展为“declarationdeclaration”。

int a, b; 中,我们可以有一个用逗号分隔的标识符列表,因为 init-declarator-list 的语法允许这样做。

(init-declarator项在init-declarator-list中也可以是“声明符 = initializer”,这就是在声明中进行初始化的方式。)

  1. In the statement a=5,b=9; is that , functioning as a separator or an operator?

是运算符。

I've read that in initialization statements, commas function as separators. However, given my understanding of what a comma operator would do, I feel like classifying this comma as an operator makes sense as well.

没有“初始化语句”这样的东西。从某种意义上说,您一定已经阅读过初始化,它可以表示为对象的 声明 的一部分。 赋值,即使是对未初始化变量的第一次赋值,在这个意义上也不是初始化。尽管句法相似。

  1. Why is int a, int b not allowed?

最终,因为语言设计者决定不应该这样做。然而,...

If the comma was allowed to behave as an operator, then certainly this would make sense, right?

不,不是特别是。要使 , 在那里充当运算符,int aint b 需要是 表达式 ,作为其操作数。他们不是。相反,它们每个都是 声明 的大部分。其中的区别是声明不计算值。

int a would be evaluated first and it would have the side effect of labeling some place in memory with the identifier of a and then int b would be processed in a similar way.

也许在其他一些语言中它可以那样工作。在 C 中,它没有。

Therefore, it seems as though the compiler does not want to alter the interpretation of the , in this case (i.e. it only ever wants to think of it as a separator).

comma-as-separator 是声明的 C 语法的一部分(除其他外)。 comma-as-operator 是表达式的 C 语法的一部分。如果它让你感到困惑或者你不喜欢它,那么你可以避免在声明中使用 comma-as-separator :相反,写

int a;
int b;

一些 C 风格指南要求,事实上,而不是在同一语句中声明多个变量。