Karnataka KSEAB SSLC JTS Programming in ANSI C study materials
Karnataka KSEAB SSLC JTS Programming in ANSI C study resources

The Counter That Would Not Reset

Karnataka KSEAB SSLC JTS Programming in ANSI C · Put your knowledge to work in context.

All case studies

The Counter That Would Not Reset

In a Shivamogga classroom, a student writes a recursive function to add the digits of a number and a static variable to count how many times the function is called: int sumdig(int n) { static int calls = 0; calls++; if (n == 0) return 0; return n % 10 + sumdig(n / 10); } In main the student calls sumdig(472) and then sumdig(85), printing calls through a printf placed inside the function. The first call reports counts 1, 2, 3, 4; the second call continues from 5 instead of starting again. The same student writes int larger(int a, int b) { if (a > b) return a; } and calls printf("%d", larger(3, 9)); which prints an unpredictable value. The teacher also asks why calls is not reset even though the declaration text looks like it executes each time.

1. Explain why calls continues from 5 on the second top-level call, and describe two ways to count per top-level call correctly.

Read the worked answer

static int calls = 0; inside a function is initialised once, before main begins, and the object lives for the entire program - it is not recreated on each call's stack frame. All recursive calls share that single object, so sumdig(472) produces counts 1, 2, 3, 4, and the later sumdig(85) continues at 5, 6, 7. The declaration text is written inside the function, but its storage duration is static, so initialisation happens only once.

Two correct approaches:

  1. Use a wrapper: keep sumdig pure and let a separate function hold an ordinary local int calls = 0;, passing &calls down if needed.
  2. Pass the counter by pointer: int sumdig(int n, int *calls) and increment *calls; the caller owns the counter and can reset it per call.

A deliberate calls = 0; reset function works too, but it is easy to forget and makes the recursion depend on hidden global state.

2. Why does larger(3, 9) print an unpredictable value? How should the function be written?

Read the worked answer

larger(3, 9) evaluates a > b, which is false, so the if body is skipped and control reaches the closing brace of a function declared to return int without returning any value. The C standard makes this undefined behaviour; the printed value may be whatever happens to be in the return register, which is why it looks random and can change between builds or optimisation levels.

A compiler will often warn "control reaches end of non-void function" - that warning should never be ignored. Correct versions:

int larger(int a, int b) {
    return (a > b) ? a : b;
}

or add return b; after the if. Every path through a non-void function must return a value of the declared type.

3. Where is calls stored, and what would change if auto or register were used instead of static?

Read the worked answer

calls has static storage duration and is stored in the program's data segment (initialised data), not on the call stack. It exists for the whole run and keeps its last value between calls.

If auto were used, each invocation would create a fresh variable on the stack, initialised to 0, so the count would always be 1 inside each call and recursion could not accumulate a total. register is only a hint that the variable be kept in fast storage; it cannot be combined with static, so it is not a substitute for persistent state. The keyword changes lifetime and initialisation, not merely visibility: static at block scope gives no linkage but full-program lifetime.