无效函数调用作为表达式

时间:2019-06-29 13:06:37

标签: c

根据C标准,很明显,常规函数调用是来自定义的表达式:

  

表达式是一个运算符和操作数的序列,它们指定值的计算,或者指定对象或函数,或者产生副作用,或者执行它们的组合。运算符的操作数的值计算在运算符结果的值计算之前进行排序。   (6.5.1)

由于()是运算符,并且它返回一个值,因此常规函数调用显然是表达式。

但是那些不返回值的对象似乎不符合该定义。函数名称本身可以(因为它指定了一个函数),但这不是函数调用。

该标准确实明确指出函数调用是一个表达式,并且它可以返回void,但这似乎与表达式的定义冲突。我想念什么?

4 个答案:

答案 0 :(得分:4)

无论函数的返回类型如何,调用函数都是表达式。 C的语法与其类型系统正交。它们是语言的独立部分。在语法上func();是一个表达式语句

expression_statement
    : ';'
    | expression ';'
    ;

postfix_expression
    : primary_expression
    | postfix_expression '[' expression ']'
    | postfix_expression '(' ')'
    | postfix_expression '(' argument_expression_list ')'

对于void结果,您可以做的事情很少。您不能将其分配给变量,因为不允许使用void变量。如果func()的结果为void,则可以使用四个运算符:

  • 括号:(func())
  • 逗号排序:func(), 42
  • 三元运算符:42 ? func() : func()
  • 从无到有:(void) func()

您还可以返回void结果:

return func();

最后,在for(init; condition; increment)循环中,这三个部分都是表达式。 init increment (但不是 condition )可以是void

for (func(); 42; func()) { }

其中很少有用,没有一个是好的样式,但是它们都是合法的。

答案 1 :(得分:3)

关于void的第6.5条第1款并未被完全考虑。 C标准不完善,存在许多缺陷。应当将本段作为一般说明,以方便读者阅读,而不是对表达式的精确数学说明。

答案 2 :(得分:1)

据说:

  

表达式是

的一系列运算符和操作数      
      
  • 指定值的计算,或
  •   指定对象或函数的
  •   
  • 产生副作用
  •   
  • 或执行其组合。
  •   

指定值的计算只是可能性中的一个void函数调用将是“产生副作用”的函数。


C中的expression语句中的任何表达式均被视为void表达式。 C11 6.8.3 Expression and null statements p2

  
      
  1. 表达式语句中的表达式因其副作用而被评估为void表达式。 153)
  2.   
     

153) ,例如赋值和具有副作用的函数调用。

即在 statement

表达式中
a = 5;

a = 5是一个 void 表达式,仅对其副作用进行评估,即将值5分配给a,而不用于计算a即使a = 5可以用于其他上下文中的值的计算。同样,您可以编写a;,即使它没有表达式,也可以合法使用表达式“评估其副作用”。它并不会在那里停止表达。

逗号运算符的LHS是无效表达式。可以在? :中使用void表达式-然后两个分支都将是void表达式,而整个表达式本身将是void表达式。

答案 3 :(得分:0)

C语言中的表达式可以为空。 这样的表达式没有值,因此无法将其分配给对象。 而且,任何表达式都可以转换为空。