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

问题描述

在阅读了Stack Overflow帖子(What does the comma operator,do?)上的几个答案后,我正在和, 运算符一起玩耍。此外,在阅读了这篇文章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",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。因此,在这种情况下,似乎编译器不想更改,的解释(即,它只想将其视为分隔符)。

非常感谢您的解释!谢谢〜

解决方法

  1. 在语句a=5,b=9;中,,是充当分隔符还是运算符?

它是一个运算符。

我已经在初始化语句中读取了逗号 用作分隔符。但是,鉴于我对 逗号运算符会这样做,我想将此逗号归类为 运算符也很有意义。

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

  1. 为什么不允许int a,int b

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

如果允许逗号作为运算符,那肯定是有道理的,对吧?

不,不是特别。为了使,在那里充当运算符,int aint b必须是 expressions 作为其操作数。他们不是。相反,它们都是声明的大部分。区别在于声明不评估值。

int a将首先被评估,其副作用是 用标识符a标记内存中的某个位置,然后int b将以类似的方式处理。

也许以其他语言可以这样工作。在C语言中则没有。

因此,似乎 编译器不想更改,中的解释 这种情况(即,它永远只想将其视为分隔符)。

逗号分隔符是C语言声明语法的一部分(除其他外)。逗号运算符是C语言表达式的一部分。如果它使您感到困惑或不满意,则可以避免在声明中使用逗号分隔符:相反,请写

int a;
int b;

实际上,某些C样式指南要求不要在同一语句中声明多个变量。

,

C中的声明的定义(尤其是)类似于

declaration:
    declaration-specifiers init-declarator-list ; 

其中术语init-declarator-list的定义如下

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

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

int a,b;

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

此声明

a = 5,b=9; 

确实是带有逗号运算符表达式的语句。

此声明

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

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

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

int a,int b; 

因为声明说明符int用于init-declarator-list.

对于逗号运算符,则按照C标准(6.5.17逗号运算符)

2逗号运算符的左操作数被评估为void 表达;在评估和 正确的操作数。然后评估正确的操作数;结果 有其类型和价值

您可以使用逗号运算符作为变量的初始化器,例如

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++,a + b );

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

    return 0;
}

其输出为

a = 10,b = 20
a = 11,b = 21,c = 32
,
  1. 在语句中a = 5,b = 9;是作为分隔符还是运算符?

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

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

所以a=5,b=9;是“ 赋值表达式 , 赋值表达式 ;”。

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

  1. 为什么不允许int a,int b?

在C语法中:

  • 这是声明(6.7)。
  • 它由声明说明符和后跟 init-declarator-list 和后跟;(6.7)组成。
  • 声明说明符可以是单个 type-specifier (6.7),即int(6.7.2)。
  • init-declarator-list 是由逗号(6.7)分隔的 init-declarator 的列表。
  • 初始声明符可以是声明符(6.7)。
  • 声明符可以是标识符,例如ab(6.7.6)。

因此int a,b;是有效的声明。 C语法中没有规定以逗号分隔的声明列表。语法中的任何内容都不能使任何内容扩展为“ 声明声明”。

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

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