C语言中函数调用操作符的结合性



我正在讨论C操作符的结合性。

在这里我发现了这样一个事实,即函数调用运算符()具有从左到右的结合性。但是,只有当表达式中出现多个具有相同优先级的操作符时,结合性才会发挥作用。但是我找不到任何涉及函数调用运算符的例子,其中结合律起着至关重要的作用。

例如,在语句a = f(x) + g(x);中,结果取决于求值顺序,而不是两个函数调用的结合性。类似地,调用f(g(x))将首先求函数g(),然后求函数f()。这里我们有一个嵌套的函数调用,同样,结合律没有起任何作用。

该优先级组中的其他C操作符是数组下标[]postfix ++postfix --。但是我找不到任何涉及这些操作符与()的组合的例子,其中结合律在表达式求值中起作用。

所以我的问题是函数调用的结合性被定义为从左到右影响C中的任何表达式吗?任何人都可以提供一个例子,其中函数调用运算符()的结合性在表达式评估中是否重要?

下面是一个函数调用操作符左右结合性的例子:

#include <stdio.h>
void foo(void)
{
    puts("foo");
}
void (*bar(void))(void) // bar is a function that returns a pointer to a function
{
    puts("bar");
    return foo;
}
int main(void)
{
    bar()();
    return 0;
}

函数调用:

bar()();

等价于:

(bar())();

除了@GrzegorzSzpetkowski的回答,你还可以有以下内容:

void foo(void) { }
int main(void) {
    void (*p[1])(void);
    p[0] = foo;
    p[0]();
    return 0;
}

这将创建一个函数指针数组,因此可以将数组下标操作符与函数调用操作符一起使用。

函数应用程序关联到左边的语句在C语言定义中是完全冗余的。这种"结合性"隐含在函数参数列表出现在函数表达式本身的右边,并且必须包含在圆括号中。这意味着对于给定的函数表达式,其参数列表的范围永远不能有任何疑问:它从函数表达式后面的强制左括号扩展到匹配的右括号。

函数表达式(通常只是一个标识符,但可能更复杂)本身可能是一个(裸)函数调用,如f(n)(1,0)中所示。(当然,这要求f(n)返回的值是可以用参数列表(1,0)调用的东西,C有一些可能性,c++更多,但这些是语义上的考虑,只有在解析之后才会发挥作用,所以在结合性讨论中应该忽略它们。)这意味着函数调用的语法规则是左递归的(函数部分本身可以是一个函数调用);这可以表述为"函数调用关联到左边",但事实是显而易见的。相比之下,右部分(参数列表)不能是(裸)函数调用,因为需要括号,所以不能有右递归。

(a)(b)(c)为例(我在这里添加了多余的括号,以暗示对称和可能的歧义)。这里的(b)(c)本身可以被看作是对b(加了多余括号)的调用,并带有参数c;然而,这样的调用不能被解释为a的参数,因为它需要像(a)((b)(c))一样额外的括号。因此,在不提及结合性的情况下,很明显,(a)(b)(c)只能意味着使用参数b调用a,并且使用参数c调用结果值。

最新更新