问题描述
在阅读了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=5
和b=9
;但是,最下面的代码(代码2)不会使它超出编译器,并引用int a,int b ;
行作为罪魁祸首。
这两个代码段中捆绑了很多问题,但我会列出我最关心的问题:
-
在语句
a=5,b=9;
中,,
是充当分隔符还是运算符?我已经读过,在初始化语句中,逗号用作分隔符。但是,鉴于我对逗号运算符的理解,因此我觉得将此逗号分类为运算符也很有意义。 -
为什么不允许
int a,int b
?如果允许逗号充当运算符,那么这肯定是有道理的,对吗?int a
将首先被评估,其副作用是使用标识符a
标记内存中的某个位置,然后以类似的方式处理int b
。因此,在这种情况下,似乎编译器不想更改,
的解释(即,它只想将其视为分隔符)。
非常感谢您的解释!谢谢〜
解决方法
- 在语句
a=5,b=9;
中,,
是充当分隔符还是运算符?
它是一个运算符。
我已经在初始化语句中读取了逗号 用作分隔符。但是,鉴于我对 逗号运算符会这样做,我想将此逗号归类为 运算符也很有意义。
没有“初始化语句”之类的东西。在您一定已经读过的意义上讲,初始化可以表示为对象的声明的一部分。 赋值,即使是对未初始化变量的第一个赋值,在这种意义上也不是初始化。尽管有句法相似性。
- 为什么不允许
int a,int b
?
最终,因为语言设计者决定不应该这样做。但是,...
如果允许逗号作为运算符,那肯定是有道理的,对吧?
不,不是特别。为了使,
在那里充当运算符,int a
和int 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
,
- 在语句中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;
是两个赋值表达式,它们之间用逗号连接并以分号结尾,从而形成一个语句。
- 为什么不允许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)。
- 声明符可以是标识符,例如
a
或b
(6.7.6)。
因此int a,b;
是有效的声明。 C语法中没有规定以逗号分隔的声明列表。语法中的任何内容都不能使任何内容扩展为“ 声明,声明”。
在int a,b;
中,我们可以有一个标识符列表,用逗号分隔,因为 init-declarator-list 的语法允许这样做。
( init-declarator-list 中的 init-declarator 项目也可以是“ declarator = initializer >”,这就是在声明中进行初始化的方式。)