0

In the numberOfDigits function, I didn't assign a value to the digits variable because by default it's 0. But then in the printf statement for digits variable it got printed as 168.

I got the expected output after I assign zero to the digits variable. So, my question: is it necessary to assign values for the variables in a user define function? If yes why?

#include <stdio.h>

void numberOfDigits(int num);

void main()  
{   
    int num;
    printf("Enter integer :");
    scanf("%d",&num);
    numberOfDigits(num);
}

void numberOfDigits(int num)
{
    int nc=num, digits=0;

    while(nc>0)
    {
        nc=nc/10;
        digits++;
    }
    printf("Number of digits in %d are %d\n",num,digits);   
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 3
    *by default it's 0*, where did you hear that? There is no default value for auto variables. – alex01011 Oct 14 '21 at 18:07
  • **global and static** variables default to 0, local (auto) variables don't have one. – SuperStormer Oct 14 '21 at 18:14
  • Does this answer your question? [Why are global variables always initialized to '0', but not local variables?](https://stackoverflow.com/questions/14049777/why-are-global-variables-always-initialized-to-0-but-not-local-variables) – SuperStormer Oct 14 '21 at 18:17

3 Answers3

3

From the C Standard (6.7.9 Initialization)

10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

Within the function numberOfDigits the variable digits has automatic storage duration because it is declared (in a block scope) without a storage class specifier. So if it is not initialized explicitly then its value is indeterminate. And applying the increment operator results in undefined behavior.

If you will declare the variable for example like

static int digits;

then it will be zero-initialized (only once).

Pay attention to that the function has a bug. If the user will pass to the function zero ( 0 ) then the function will report that the number has 0 digits though it has one digit equal to 0.

You need to substitute the while loop for the do while loop shown below

do
{
    digits++;
} while ( nc /= 10 );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

I am assuming you are quite new to C.

Maybe it does help to review at what place in memory different types of variables are stored. Local variables, variables created in functions (such as in your case), are always allocated memory in the program stack. However, there is no real guide-line that promises your program that the stack is zero'ed out. This means, when you are creating a local variable, it gets assigned memory in the stack and that memory space can be a non-zero value. Then when you print that integer (without assigning it) you will see what was stored before at the same memory address.

Hence, there is no guarantee that a value is 0 when you do not define it.

You can learn more here.

Fabian B
  • 171
  • 8
  • 2
    Re “Local variables, variables created in functions (such as in your case), are always allocated memory in the program stack”: This is not correct. Typical general-purpose C implementation nominally use stack for these things, but optimization may use registers instead or even eliminate objects entirely. Special-purpose C implementations for low-memory embedded systems may dedicate memory locations for local objects, as if they were static (and, to make this work, may limit the amount of recursion allowed). – Eric Postpischil Oct 14 '21 at 21:21
  • Additionally, because of optimization and the rules of the C standard, using the value of an uninitialized object may produce some value other than what is stored in its memory location, even if it has been assigned memory on the stack. – Eric Postpischil Oct 14 '21 at 21:22
  • @EricPostpischil Could you elaborate on your last point? "using the value of an uninitialized object may produce some value other than what is stored in its memory location, even if it has been assigned memory on the stack" – Tarik Oct 15 '21 at 02:07
  • @Tarik: Suppose a program has the source code `int x = 3; f(x); x = 5; printf("%d\n", x);`. If `x` is assigned the stack location `4(sp)`, the compiler could generate assembly code for this such as `move #3, 4(sp)`, `move 4(sp), r0`, `call f`, `move #5, 4(sp)`, `move AddressOfFormatString, r0`, `move 4(sp), r1`, `call printf`. But that is wasteful; more efficient code is `move #3, r0`, `call f`, `move AddressOfFormat, r0`, `move #5, r1`, `call printf`. In other words, optimization removes unnecessary stores to and loads from memory. Registers are used directly. – Eric Postpischil Oct 15 '21 at 11:02
  • … Then consider what happens when you do not initialize `x`. If the code is just `f(x); printf("%d"\n", x);`, then the code generated could be `call f`, `move AddressOfFormat String, r0`, `call printf`. There are no moves to the registers because `x` was never initialized or assigned. In this case, the called routine gets whatever was in a register. For the call to `f`, `f` gets the contents of `r0`, because that is where it expects its first argument to be. For the call to `printf`, `printf` gets the contents of `r1`, because that is where it expects its second argument to be… – Eric Postpischil Oct 15 '21 at 11:05
  • … So, when the code `f(x); printf("%d\n", x);` is executed, it can appear as if `f` and `printf` are called with different values of `x`, because the fact `x` is never initialized or assigned means it is never properly connected to any specific value, and the code just picks up values from however the generated assembly code happens to get values. This is just one example; there are other ways optimization can make similar code behave in unexpected ways. – Eric Postpischil Oct 15 '21 at 11:08
  • @EricPostpischil Ah, ok. Yes, indeed if things happen in registers for optimization purposes, it explains perfectly what you said. Thanks for your time Eric. – Tarik Oct 15 '21 at 12:52
0

...because by default it's 0

False, for local (automatic-duration) variables.

So, my question: is it necessary to assign values for the variables in a user define function?

Yes.

If yes why?

Because otherwise they start out with unpredictable values, making your code unreliable and broken.

See also this answer.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103