int sum(int, int)
函数)。printf("%d", sum(a,b));
编译器如何确定函数调用中使用的
,
不是逗号运算符?
注意: 我并不想在函数调用中使用逗号运算符,我只是想知道编译器如何知道它不是逗号运算符。int sum(int, int)
函数)。printf("%d", sum(a,b));
,
不是逗号运算符?
注意: 我并不想在函数调用中使用逗号运算符,我只是想知道编译器如何知道它不是逗号运算符。看一下C语言的语法。它在标准的附录A中列出了完整的语法。它的工作原理是,你可以逐个步骤地浏览C程序中的每个标记,并将其与语法中的下一个项匹配起来。在每个步骤中,你只有有限的选项,因此任何给定字符的解释都取决于它所出现的上下文环境。在语法的每个规则内部,每行都提供一个有效的程序匹配替代方案。
具体来说,如果你寻找parameter-list
,你会发现它包含一个明确的逗号。因此,每当编译器的C解析器处于“parameter-list”模式时,它找到的逗号将被理解为参数分隔符,而不是逗号运算符。括号也是如此(它们也可以出现在表达式中)。
这能够实现的原因是parameter-list
规则小心地使用了assignment-expression
规则,而不仅仅是普通的expression
规则。一个expression
可以包含逗号,而一个assignment-expression
不能。如果不是这样,语法将是模糊的,编译器在遇到参数列表中的逗号时就不知道该怎么做了。
然而,例如不是函数定义/调用中的开括号,或者if
、while
或for
语句中的开括号,将被解释为表达式的一部分(因为没有其他选项,但仅当在那一点上表达式的开头是一个有效的选择时),然后在括号内部,expression
语法规则将应用,并且这允许使用逗号运算符。
assignment-expression
非终结符,而不是expression
非终结符(如Jens的回答中所讨论的),因此禁止在parameter-list
的顶层使用逗号运算符。如果标准只做了你描述的事情而没有做这个,整个语法将是有歧义的。 - zwolT * T;
歧义需要知道“T”是什么而不仅仅是是否声明了它,因此C不是上下文无关的(因此没有CFG)。因此,我认为说C是上下文无关的并没有意义。 - user541686来自C99 6.5.17:
另一个类似的例子是数组或结构体的初始化器列表:As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.
int array[5] = {1, 2};
struct Foo bar = {1, 2};
如果要使用逗号运算符作为函数参数,应该像这样使用:
sum((a,b))
问题出在C语言的语法结构上。虽然其他人似乎喜欢引用这个例子,但真正的问题在于C99标准中函数调用的短语结构语法。是的,一个函数调用由应用于后缀表达式(例如标识符)的()
运算符组成:
6.5.2 postfix-expression:
...
postfix-expression ( argument-expression-list_opt )
与...一起
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression <-- arglist comma
expression:
assignment-expression
expression , assignment-expression <-- comma operator
逗号运算符只能出现在表达式中,即在语法中往下。因此,编译器将函数参数列表中的逗号视为分隔“赋值表达式”的逗号,而非分隔“表达式”的逗号。
(
东西)
。语法规定,您可以拥有黄色高尔夫球,它们会自动分开。或者,您可以提供一个透明的球只要您使用了两半。透明的球作为一个整体,不能打开和分离。因此:f((a,b),g)有一个“透明球”(a,b)和一个“黄球”g,因此正好有两个球,呃,参数。 - torek(
用)
“结束”:括号结束了完整的表达式上下文。 - torek{
… }
, [
… ]
和 (
… )
。它们“匹配”:如果你写 a[3}
,显然是错误的。如果你写 a[(3]
,仍然很明显是错误的。(
只有与匹配的 )
结束才能完成。这样“关闭”整个序列,使其清楚地显示哪些内容彼此对应。 - torekC99标准草案指出:
如语法所示,逗号运算符(如本子句所述)不能出现在使用逗号分隔列表项的上下文中(例如函数参数或初始化器列表)。而另一方面,在括号表达式或条件运算符的第二个表达式中可以在这些上下文中使用它。在函数调用
f(a, (t=3, t+2), c)
中,该函数有三个参数,其中第二个参数的值为5。
换句话说,“因为”。
sum
,另一个是printf
。 - Keith Thompsona/*b
。添加一些空格后问题得到解决:a / *b
。请注意,翻译时需要使内容更加通俗易懂,但不要改变原来的意思。 - Stewart