Search code examples
cpointerspass-by-referencescanfpass-by-value

Scanf - varaible per reference VS parameter per reference


I have a little knot in my head. I was just trying to explain to someone, why a little program uses pointers the way it does, and then she asked me about a different way, which should (to my knowledge) work, but doesn't. Here's the code that works:

#include <stdio.h>

void inputNums(double *valOne, double *secVal)
{
    printf("Enter your first number: ");
    scanf("%lf", valOne);

    printf("Enter your second number: ");
    scanf("%lf", secVal);
}

void sum(double valOne, double secVal )
{
    double result = valOne + secVal;
    printf("The sum is: %.2f\n", result);
}


int main()
{
    double numOne;
    double numTwo;

    inputNums(&numOne, &numTwo);
    sum(numOne, numTwo);
    return 0;
}

And here's the code that doesn't, but I don't get why:

#include <stdio.h>

void inputNums(double valOne, double secVal)
{
    printf("Enter your first number: ");
    scanf("%lf", &valOne);

    printf("Enter your second number: ");
    scanf("%lf", &secVal);
}

void sum(double valOne, double secVal )
{
    double result = valOne + secVal;
    printf("The sum is: %.2f\n", result);
}


int main()
{
    double numOne;
    double numTwo;

    inputNums(numOne, numTwo);
    sum(numOne, numTwo);
    return 0;
}

I know it's something really simple, but for the love of god, I can't figure it out. Thanks guys :)


Solution

  • There are two function calls happening in your code that need to be able to modify the data in the caller:

    • The call of inputNums(...), and
    • The call of scanf(...), which happens from inside inputNums(...)

    In order for the nested call of scanf to be able to modify data in main, scanf needs to have a pointer to the data in the main: that's the only way a C function can modify a local variable inside its caller.

    In your first example inputNums has a pointer to variables inside main so the modification works fine, while in the second example it does not have a pointer to variables of main, because you pass parameters by value. That is what breaks your second implementation.

    Here is an illustration of what is happening:

    Passing by pointer vs. passing by value

    In the first case pointers to numOne and numTwo of main are passed all the way to scanf, while in the second case scanf sees pointers to local valOne and secVal of inputNums, which is what it modifies, without touching the variables of main.