In principle, compilers may act in such cases at their discretion, within certain limits. Static variables are not used in programs just as they can be reused and theoretically in different parts of the code. Your loop can pass a pointer to a static variable to some called function and through this pointer it can be accessed even after the loop ends. In this regard, the optimizer is very careful with operations with it.
According to the results of the tests, the GCC optimizer in the first case:
int c=0; for (int i=0;i<100;++i) {...;++c;}
I did not allocate memory for variables i and c , but used 1 processor register to maintain one value, i.e. he realized that the values ​​of the variables at all iterations coincide and just threw out one of them.
In the second case:
for (int i=0;i<100;++i) {...;static int c;++c;}
the compiler allocated for the variable c memory in the data segment (and not the stack, as with the usual internal variables of functions). For the convenience of organizing transitions, the variable i began to lead in the reverse order (from 100 to 0), since the value of the variable i itself is only needed for counting the cycle and is not used anywhere else. Static variable c optimizer at each iteration of the cycle gets out of RAM, adds 1 and puts back into RAM. That in terms of code efficiency is clearly a slow operation.
Another thing to add is that if a static variable lies in a data segment, it differs from the global one only by its scope. In this regard, the use of such variables in a multithreaded application will create a lot of problems and will require taking locks before working with it.
Based on this, we can conclude that static variables should be used when they are really needed to implement a specific algorithm.