返回语句中的奇怪表达式

6
我发现了一个递归函数,让我有些惊讶。这个函数计算出数组中出现的所有负数的数量:
int count_negative(int arr[], int n)
{
  if ( n > 0 )
    return (*arr < 0) + count_negative( ++arr, n - 1 );
  return 0;
}

有人能解释一下这行代码的意思吗:

return (*arr < 0) + count_negative( ++arr, n-1 );

谢谢你


1
这是一个相当糟糕的递归实现;它不符合尾调用的要求,因此与迭代实现相比,性能将会受到影响。 - cdhowie
3
这个 (*arr ...) + count_negative( ++arr, ... 会引发未定义行为吗? - alk
@cdhowie:GCC 看起来可以很好地进行尾调用优化。 - ninjalj
3个回答

6

(*arr < 0) 比较了数组的第一个元素和零。表达式的结果可能是 1(第一个元素为负数)或者 0(第一个元素为正数或零)。因此,负数元素的数量是这个表达式和数组尾部中负数元素数量之和。


3
*arr指向数组arr的第一个元素(或者更精确地说,指向在这个特定调用中传递给函数的arr的一部分)。
count_negative( ++arr, n-1 )是一个递归调用,但由于++arr,所以在这个调用内,我们计算了数组的下一个元素,并且n-1参数加上if (n > 0)保证我们只计算arr数组内的元素。

2
原则是,不必在要检查的元素上保留索引,因为 arr 是一个指针,修改它不会改变数据,可以将 arr 本身用作数组数据的迭代器。所以,*arr < 0 检查当前指向的元素是否为负数(如果是,它会返回 1,否则返回 0),而 ++arr 将光标递增到数组中的下一个位置,然后将其递归传递到数组的其余部分进行检查。这是函数式语言中处理列表的一个非常著名的思想,在其中通常使用列表的第一个元素(头部)并递归地处理剩余的列表(尾部)。

2
现在我明白了,即 (*arr < 0) 是根据它是否为负数而生成 1 或 0。 - cheroky
没错。在 C 语言中,1true 是相同的值。 - didierc
1
2 也是真的...;-) - alk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接