我正在查看此页面:https://en.cppreference.com/w/c/language/operator_precedence
引起我注意的是,括号运算符的 only 描述是 function call 。这是否意味着表达式x = a * (b+c)-(d*e)
有两个函数调用?
我在C grammar和C standard中进行了搜索,但找不到任何支持或矛盾的内容。
答案 0 :(得分:6)
括号可以用作函数调用运算符,但这并不是它们唯一的用途。如您的示例一样,它们也用于表达式分组。
您要查找的是C standard的6.5.1节,其中讨论了主表达式:
语法
1
primary-expression: identifier constant string-literal ( expression ) generic-selection
...
5 带括号的表达式是主要表达式。其类型和值与未带括号的表达式相同 表达。它是左值,函数指示符或无效值 如果未加括号的表达式分别是 一个左值,一个函数指示符或一个空表达式。
如上所述,括号可用于对表达式进行分组。
在6.5.2节中有关Postfix表达式的详细信息,用作函数调用运算符:
postfix-expression: ... postfix-expression(argument-expression-list opt) ...
在您的表情中:
x = a * (b+c)-(d*e)
此处使用括号匹配主表达式,但不匹配后缀表达式。
此外,除表达式分组外,在语言语法的其他部分也使用了括号。关于选择语句的第6.8.4节在if
和switch
语句的语法中使用括号:
- 如果(表达式)声明
- if( expression ) statement else statement
- switch( expression ) statement
关于迭代语句的第6.8.5节在while
和for
语句的语法中也使用括号。
- while( expression ) statement
- 在(表达)时执行声明;
- 表示( expression opt ; expression opt ; expression opt )声明
- 表示(声明 expression opt ; expression opt )声明
答案 1 :(得分:4)
函数调用是后缀表达式。
这些表达方式在这里
x = a * (b+c)-(d*e);
subexpressioins (b+c)
和(d*e)
是主要表达式。您可以将任何表达式括在括号中,然后得到一个主表达式。
例如,您甚至可以通过以下方式重写表达式语句
( x = ( ( ( a ) * (b+c) )-(d*e) ) );
此表达式语句中包含以下主要表达式
( a )
(b+c)
(d*e)
( ( a ) * (b+c) )
( ( ( a ) * (b+c) )-(d*e) )
( x = ( ( ( a ) * (b+c) )-(d*e) ) )
以下是一些后缀表达式的示例
( *p )() // a function call
a[n] // using the subscript operator
x++; // using the postfix increment operator
函数调用的定义是
postfix-expression:
primary-expression
postfix-expression ( argument-expression-listopt )
根据C标准(6.5.2.2函数调用)
1表示被调用函数(92)的表达式应具有类型 指向返回void或返回完整对象类型的函数的指针 除了数组类型。
以下是一些奇怪的函数调用示例::)
#include <stdio.h>
void f( void )
{
printf( "Hello " );
}
void g( void )
{
puts( "Broman" );
}
int main( void )
{
void ( *funcs[] )( void ) = { f, g };
void ( **p_func )( void ) = funcs;
( *p_func++ )();
p_func[0]();
}
程序输出为
Hello Broman
在这些通话中要考虑到这一点
( *p_func++ )();
p_func[0]();
表达式( *p_func++ )
是主要表达式,表达式p_func[0]
是后缀表达式(请参见上面的后缀表达式的部分定义)
答案 2 :(得分:2)
不。 identifier(将标识符作为函数调用。如果没有标识符或括号后紧跟的完整表达式,则不会调用。
当我第一次学习c时,我遇到了相反的问题。我不知道为什么clrscr;
没有清除屏幕。 (这是一个表达式,其结果为指向clrscr
的指针,但不执行任何操作。)
实际上,您可以具有指向函数的类型指针的表达式,并且可以使用()调用这些表达式,并且两者之间的语法是完全明确的。因此clrscr();
是一个函数调用,(clrscr)()
也是如此。在到达函数指针时,我们也可以执行resolve_function()()
。该操作始终(在表达式之后,而不是在运算符之后。如果是在运算符之后,则必须将括号分组。