When you have recursive function calls, you have multiple "instances" of a function active, calling and returning to each other. To visualize this, I find it useful to imagine that, instead of a C program running on a computer, you have a bunch of people in a room, and you all give them an identical set of instructions, and then you ask them to start solving a problem for you. For the code in your question it would go something like this.
You pick a person and say, "Hey, John, here's an array of size 3: [1, 2, 3]. Can you tell me how many times the number 2 appears in it?"
John takes the array from you, and he looks at his instructions. The array is not of size 0, so he doesn't tell you 0. The last element of his array is not 2, so he doesn't do the second thing, either. But to do the third thing, he needs to make a recursive call, so he picks someone else in the room and he says, "Hey, Mary, here's an array of size 2: [1, 2]. Can you tell me how many times the number 2 appears in it?"
Mary takes the array from John, and she looks at her instructions. The array is not of size 0, so she doesn't tell John 0. But the last element of her array is 2, so she does do the second thing. But to do the second thing, she also needs to make a recursive call, so she picks someone else in the room and she says, "Hey, Fred, here's an array of size 1: [1]. Can you tell me how many times the number 2 appears in it?"
Fred looks at his instructions. The array is not of size 0, so he doesn't tell Mary 0. The last element of his array is not 2, so he doesn't do the second thing. He, too, needs to make a recursive call to do the third thing, so he picks someone else in the room and says, "Hey, Jane, here's an array of size 0: []. Can you tell me how many times the number 2 appears in it?"
Jane looks at her array, and the size is 0. So she says, "Fred, the number of times that 2 appears in that array is: 0".
That's what Fred was waiting for. Fred was working on the third return statement, so whatever he hears from Jane is his answer, too. He says, "Mary, the number of times that 2 appears in that array is: 0".
That's what Mary was waiting for. But she was working on the second return statement, so she adds 1 to whatever she hears from Fred. She says, "John, the number of times that 2 appears in that array is: 1".
That's what John was waiting for. John was working on the third return statement, so whatever he hears from Mary is his answer, too. He says to you, "The number of times that 2 appears in that array is: 1".
And now you have your answer!
I used to teach a C programming class, and one day I gave everyone in the class a handout which was some human-readable instructions on how to do a recursive, in-order traversal of a binary tree. Then I handed a "binary tree" -- a piece of cardboard with a bunch of yellow stickies arranged on it in a tree-like structure -- to a random student in the front row, to start traversing. It was absolute pandemonium, but also great fun. (I think. I thought it was fun, anyway!)
returnsimply returns to the place from where the function has been called, there is no magic.returnis taken conditionally, the function stops executing at that point and any otherreturnisn't considered. The first oneif(arr_len == 0) return 0;ends the recursion, the other two determine which recursive path to take.return 0;doesn't involve a call tocount, whereas the other branches do. That makes it the base case rather than a recursive case.return, returns a 0, how is that thecount()function still returns the counts of appearances? At the end, only returns what the finalreturnsends back tomainright? That in this case would be a zero