Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange expression in the return statement

I found a recursive function that left me a little surprised this function counts all negative numbers which appear in an array :

int count_negative(int arr[], int n)
{
  if ( n > 0 )
    return (*arr < 0) + count_negative( ++arr, n - 1 );
  return 0;
}

Can someone explain this line :

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

Thank you

like image 879
cheroky Avatar asked Nov 15 '14 18:11

cheroky


3 Answers

(*arr < 0) compares first element of the array with zero. The result of the expression can be either 1 (first element is negative) or 0 (first element is positive or zero). So, the number of negative elements is the sum of this expression and the number of negative elements in the tail of the array.

like image 55
Nikolai Avatar answered Nov 17 '22 05:11

Nikolai


*arr points to the first element of arr array (or, more precisely, the part of the arr that has been passed to the function in this particular call).

count_negative( ++arr, n-1 ) is a recursive call but because of ++arr, inside this call we count the next element of the array and n-1 argument, togeher with the if ( n > 0 ) guarantees that we will count only elements inside the arr array.

like image 37
syntagma Avatar answered Nov 17 '22 05:11

syntagma


The principle is that instead of keeping an index on the element being inspected, since arr is a pointer and modifying it will not change the data, one may instead use arr itself as the iterator on the array data.

So, *arr < 0 checks if the current pointed element is negative (it will yield 1 if so, 0 if not), and ++arr increments the cursor to the next place in the array, which is then passed on recursively to check the rest of the array.

This is a very well known idea in functional languages working with lists, where you often work on the first element of the list (the head) and recurse on the remaining of the list (the tail).

like image 2
didierc Avatar answered Nov 17 '22 06:11

didierc