【问题标题】:The comma operator in a function argument函数参数中的逗号运算符
【发布时间】:2018-03-21 23:24:36
【问题描述】:

我正在阅读 GNU C 手册的摘录:

您使用逗号运算符来分隔两个(表面上相关的)表达式。

后面的描述:

如果你想在函数参数中使用逗号操作符,你需要 在它周围加上括号。那是因为函数中的逗号 参数列表具有不同的含义:它们分隔参数。

到目前为止,一切都很好。奇怪的是:

foo (x, (y=47, x), z); 是一个函数调用,只有三个 论据。 (第二个参数是(y=47, x)。)

问题是:参数是如何压栈的,如何从函数内部访问它?

【问题讨论】:

  • 函数接收参数 (x, x, z)。问题出在哪里?
  • 参数不必被压入堆栈。堆栈甚至可能不存在
  • 据我所知,问题在于 OP 正在想象整个带括号的构造被“推入”堆栈/作为参数传递。错过了首先评估这一点。
  • a) 这不是 GNU 扩展,而是标准 C 行为,b) 确实不需要堆栈,并且在 x86-64 中,参数甚至不会被压入堆栈,参数是正如苏拉夫所说...
  • 评估三个参数中的每一个,并将结果传递给函数。请记住,C 是按值调用,而不是按名称调用(您认为它的行为方式与 Algol 中的行为方式相同)。

标签: c arguments expression comma-operator


【解决方案1】:

在你的情况下,

  foo (x, (y=47, x), z);

在功能上类似于

  foo (x, x, z);

根据逗号运算符的属性,先计算左手操作数并丢弃结果,然后再计算右手操作数,这就是结果。

为了完整起见,引用C11,第 §6.5.17 章

逗号运算符的左操作数被评估为 void 表达式;有一个 其求值与右操作数求值之间的序列点。那么右边 评估操作数;结果有它的类型和值。

注意点:变量y 将被更新,因为 LHS 操作数被评估为 void 表达式,但对 此函数调用没有影响。如果y 是一个全局变量并在foo() 函数中使用,它将看到一个初始值47

说是回答

参数是如何压栈的

非常依赖于实现(架构)。 C 没有指定函数参数传递的任何顺序,并且某些架构可能根本不使用“堆栈”来传递函数参数!!

【讨论】:

  • 具有将 y 设置为 47 的副作用,这可能是在全局范围内。
  • @Bathsheba 显然是先生,但这对 this 情况下的函数 call 没有任何影响。
  • 因此,我不会将其描述为“功能相似”。
  • @Bathsheba 好的,我详细说明了我的答案。任何可以避免任何误解的替代措辞?请随时编辑。谢谢。 :)
  • @JohnBollinger 我知道 C 计算表达式然后将结果作为参数传递。但是对于逗号运算符的这种情况有点奇怪。现在很明显,左操作数被评估然后被丢弃。现在这是有道理的,因为它是被评估的第二个参数,其结果作为参数值传递。
猜你喜欢
  • 2011-05-09
  • 1970-01-01
  • 2011-01-24
  • 2013-07-11
  • 2013-06-27
  • 1970-01-01
  • 2012-08-30
  • 2019-08-05
相关资源
最近更新 更多