2

I'm new in this community, and I'm trying to understand why this recursive function not get a stack overflow,when I use the post increment (c++) in the call of the function, this passes a value of 0 (i see that when i debug), but when the next function is called, it have a value of 1. I dont understand when the post increment is applied, and why if im passing to the function the value of 0 , in the first argument is doing s+1;

#include <stdio.h>
#include <string.h>
#define LARGO 20

char *esta (char s[], int c){
 if(strlen(s))
    printf("\n %s", esta(s+c,c++));
 return s;
}

int main()
{
 char cad[LARGO]= {"hello"};
 int c=0;
 printf("\n %s", esta(cad,c++));
}

P.S. : Sorry if my english is not the best, It isn't my main language and i try to explain as well i could; and if it is something is not clear tell me and i change it.

Juampi
  • 33
  • 4
  • Function `esta` will be called with argument `c` equal `0` forever... Since you're using recursion, this will pretty quickly result with a stack overflow. – barak manos Jun 29 '16 at 20:19
  • @barak But that's just the question. As written, `c` should equal zero forever, but for some reason it doesn't (or seems not to). The recursion collapses normally instead of overflowing the stack. – Juan Tomas Jun 29 '16 at 20:21
  • 2
    The `s+c` expression may be evaluated before or after the `c++` expression. I think that the language standard does not define which expression inside a function-call will be evaluated first. In your case, it is probably evaluated after (`c++` and then `s+c`). But in any case, my comment above is wrong, because although argument `c` is always `0`, argument `s` **is** incremented, so the code will complete successfully. Replace `c++` with `c+1` if you want to avoid this kind of undefined behavior. – barak manos Jun 29 '16 at 20:23

2 Answers2

7

The order in which arguments are evaluated is undefined, so the compiler can choose any order it wants to. It seems in your case, it's first evaluating c++ to 0, and then s+c evaluates to s+1.

tsandy
  • 911
  • 4
  • 10
  • 1
    Not sure why this got downvoted. It actually makes sense. – Juan Tomas Jun 29 '16 at 20:24
  • Additionally, there's no sequence point between the evaluation of the two arguments -- only one after all the arguments are evaluated but before the actual function call; so there's undefined behaviour for that reason too, as there would be with eg. `x = c + c++;`. Hypothetically, the arguments could be evaluated right to left and still have the `s + c` argument mean either `s + 0` *or* `s + 1` (the side effect of the increment might happen after both arguments are evaluated, or earlier). – Dmitri Jun 29 '16 at 20:57
2

See wikipedia Sequence point. In particular item #4 gives full explanation:

A sequence point defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.

  1. Before a function is entered in a function call. The order in which the arguments are evaluated is not specified, but this sequence point means that all of their side effects are complete before the function is entered. In the expression f(i++) + g(j++) + h(k++), f is called with a parameter of the original value of i, but i is incremented before entering the body of f.

In other words: compiler is assigned to do a tough job here. It must pass the original value which was there before POST-increment (because it is how POST-increment works) and at the same time perform all side effects BEFORE entering the function esta. Among these side effects is increment the value of c. And, since the order in which the arguments are evaluated is not specified it happens so that your compiler evaluates c++ first, and then does s+c which in this case means s+1. Hence your line is shorter and shorter and eventually strlen(s)==0 when you exit from the recursion and print string remainders at each iteration.

Community
  • 1
  • 1
fukanchik
  • 2,811
  • 24
  • 29