1

I'm getting this error while trying to define a local static variable.

Initializer element is not constant.

I want to retain the first value of var inside this recursion. How to pass this? Hope you also clarify the side effects of assigning arguments to the local static variables to be prevented.

int function(int var)
{
static int index=var;
//some code ...
    return var==0?1:function(var-1);
}
IDEN
  • 21
  • 1
  • 9

2 Answers2

2

the static variable is initialized before the function even starts. It's like a global variable, only with function scope. The compiler cannot use a value that it doesn't know yet.

You could workaround this with an helper boolean:

int function(int var)
{
  static int index_is_set=0;
  static int index;
  if (!index_is_set)
  {
    index = var;
    index_is_set = 1;
  }

//some code ...
    return var==0?1:function(var-1);
}

so first time you enter the function it sets the value, sets the boolean flag to 1 so it's not overwritten by further calls.

note that this isn't very useful as a construct, since if you are to call your function recursively a second time in your program (after having obtained the result the first time, I mean), there's no way to reset the variable (unless you make index_is_set global so you can reset it from the outside).

Note that it is possible to get rid of all this static thing altogether by using the start value as an extra parameter.

int function(int var, int start_value)
{
    // ...
    return var==0 ? 1 : function(var-1,start_value);
}

First call goes like:

function(20,20);

or wrapped in a function which hides this implementation:

int function_wrapper(int var)
{
    return function(var,var);
}

the start value is passed along all calls. Consumes a bit more auto variable space, but is much cleaner, no memory effect & easier to debug.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    Yes, something along these lines is the usual approach when there is no distinguished value suitable for direct use to mean "not yet initialized". In this case, however, it looks like it might be possible to omit the extra variable by initializing `index` to, say, -1. I.e. a value that cannot possibly be a valid index. – John Bollinger Mar 10 '18 at 20:06
  • 1
    @JohnBollinger yes, in the general case it's not possible, but with some conventions, it would be. Didn't want to go that path because I don't know what OP wants to do with that. – Jean-François Fabre Mar 10 '18 at 20:08
1

The case:

static int index=var;

Is a declaration with initializer (see ISO/IEC 9899:2011 §6.7 Declarations). The statement declares a static variable initialized to a value that must be a constant defined at compile time. In plain word because the value is initialized before the execution starts the initializer must be defined before function usage.

If you want retain the first value of a recursion the way you are using isn't a good choice for many reasons:

  • The value, as seen, cannot be assigned using a not constant value
  • If it worked, the next time you enter the function it would be reassigned clearing the very first value
  • A local static variable has unlimited life, but scope limited to the local function. Then you cannot access or initialize it from external scopes.

a solution can be to pass to the function 2 variables a first value and the value passing the same value the very first call of the function:

int function(int first_var, int var)
{
    //some code ...
    return var==0?1:function(first_var, var-1);
}
...
function(5, 5);    //First call

For sake of completeness it could work by breaking your statement in a definition of the static variable without initialization (or with a generic initialization), followed by an assignment (ISO/IEC 9899:2011 §6.5.16 Assignment operators):

int function(int var)
{
static int index;    //Declaration
index=var;           //Assignement
//some code ...
    return var==0?1:function(var-1);
}

But because it will be reassigned each time the function reenters, it is only a big nonsense...

Frankie_C
  • 4,764
  • 1
  • 13
  • 30