31

我正在讨论 C 运算符的关联性这一主题。

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

例如在语句a = f(x) + g(x);中,结果取决于评估顺序而不是两个函数调用的关联性。同样,调用f(g(x))将首先评估 function g(),然后是 function f()。在这里,我们有一个嵌套的函数调用,并且关联性再次不起作用。

此优先级组中的其他 C 运算符是数组下标[]和。但是我找不到任何涉及这些运算符组合的示例,其中关联性在表达式评估中起作用。 postfix ++postfix --()

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

4

3 回答 3

44

这是一个示例,其中函数调用运算符的左右关联性很重要:

#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())();
于 2015-08-10T11:10:18.407 回答
15

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

void foo(void) { }

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

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

于 2015-08-10T11:30:26.913 回答
3

函数应用程序关联到左边的语句在 C 语言定义中是完全多余的。函数参数列表出现在函数表达式本身的右侧并且必须用括号括起来这一事实暗示了这种“关联性” 。这意味着对于给定的函数表达式,它的参数列表的范围永远不会有任何疑问:它从函数表达式之后的强制性左括号延伸到匹配的右括号。

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

例如考虑(a)(b)(c)(我在其中添加了多余的括号以表明对称性和可能的​​歧义)。这里本身(b)(c)可能被认为是b带有参数的(多余的括号)的调用c;然而,这样的调用不能被解释为 的参数a,因为这需要额外的括号,如(a)((b)(c)). 因此,没有任何提及关联性,很明显(a)(b)(c)只能表示a用 argument 调用b,而结果值用 argument 调用c

于 2015-08-11T05:44:56.350 回答