3

I'm working on my intro C course assignment and I'm tasked with the following...

  1. Write code for a function that receives two parameters (a,and b) by value and has two more parameters (c and d) by reference. All parameters are double.
  2. From main, use scanf to get two numbers, then call the function, and then display both returned values to the output in a printf statement.
  3. The function works by assigning (a/b) to c and assigning (a*b) to d.

While my knowledge is basic, I believe I understand the gists In main

      //first and second double hold the scanf inputs
      double first;
      double second;

      //unsure here - to reference c and d as parameters in the function, do I simply declare unfilled double variables here?
      double *c;
      double *d;

   printf("Enter your first number\n");
   scanf("%f\n", &first);
   printf("Enter your second number\n");
   scanf("%d\n", &second);

   //call the function, first and second by value, &c / &d by reference - correct?
   pointerIntro(first, second, &c, &d);

For the function...

float myFunction(double a, double b, double *c, double *d)
{
c = a/b;
d = a*b;


//printf statements
}

I apologize if the flow of this question is messy but its part of the process for me :P

So, for my formal questions 1. is it correct to initiate two double pointer variables (*c & *d) in main to be passed as reference in the function? 2. Am I right to call the function with the reference pointers by saying &c / &d? 3. Any other critiques of this questioning?

  • 1
    In C, lose the "by-reference" vernacular. Use "by-address". In the long run, it will make your life easier; trust me. And fyi, `c` and `d` in `main` should be regular `double`, not `double *`. Also, in your function `*c = a/b;` and similar for the subsequent line is probably you're intent. What you have there should puke at least a warning about assigning an `int` to a `int *` type. If it doesn't turn up your warnings, and treat them as errors. – WhozCraig Nov 16 '19 at 08:54
  • Yep, intro to C. the question may be poorly worded. – Jon Gardocki Nov 16 '19 at 08:55
  • "*All parameters are double.*" No. Two are `double` and two are **pointer to** `double`, that is `double*`. – alk Nov 16 '19 at 08:56
  • If within the calling function you want to store *four* `double` you need to define *four* `double`. – alk Nov 16 '19 at 09:00
  • Also take the compiler's warning serious. If the code shown does not provoke warnings, then raise the compiler's warning level. – alk Nov 16 '19 at 09:01
  • @WhozCraig: "*...`int` ...`int*`...*" err, what? – alk Nov 16 '19 at 09:03
  • I'll attempt to enact each of these responses in an update momentarily. Thank you! – Jon Gardocki Nov 16 '19 at 09:03
  • @alk lolz. man its late here. thanks for the keener eye than my scotch-inhibited pair =P – WhozCraig Nov 16 '19 at 09:04
  • 1
    @OznOg _et al_ The act of "passing by-reference" is a generic computer science term independent of language. The fact that C does not support explicit _reference types_ does not make the term _"by reference"_ invalid in this context - it is common term before C++ was even a thing. – Clifford Nov 16 '19 at 09:10
  • Don't change the question, by adding "solutions" after answers are posted - if you apply a solution from an answer and it still does not work, then either the answer is incorrect or you have a different problem and should post a _new_ question. By changing the question and adding new issues, you render existing answers incomplete or invalid, which is confusing and unfair to those who took the trouble to answer. Post a comment to an answer if you need clarification. SO is not a discussion forum. You cannot expect users to update theor answers as you change your question! – Clifford Nov 16 '19 at 09:15
  • As well as fixing the pass-by-reference semantics, you might want to initialise `first` and `second` (`scanf()` will not assign them if the entry cannot be converted), possibly check the return from `scanf()` if you care, and certainly handle `second == 0` which will cause a run-time error at `c / d`. – Clifford Nov 16 '19 at 10:07

5 Answers5

5

Variables 'c' and 'd' don't have to be pointers to pass them by reference. So you have two cases:

  1. When you define 'c' and 'd' as pointers in main function you will pass them to function like this: pointerIntro(first, second, c, d); because they are already pointers and you don't need to send their reference, you just send them.

  2. If you define 'c' and 'd' just as double variables double c, d; you will send them to the function by reference using '&' symbol like this: pointerIntro(first, second, &c, &d);.

Then in your function to actually set the values of 'c' and 'd' you will need to dereference the pointer to them like this: *c = a/b; *d = a*b;.

If you are not familiar you can check what dereferencing the pointer means here: What does "dereferencing" a pointer mean?

Code that should work:

#include <stdio.h>

void myFunction(double a, double b, double *c, double *d)
{
    *c = a / b;
    *d = a * b;
}

int main(void)
{
    double a, b, c, d;

    scanf("%lf", &a);
    scanf("%lf", &b);

    myFunction(a, b, &c, &d);

    printf("%lf %lf", c, d);
}
Harun Tucakovic
  • 146
  • 1
  • 7
  • Taking on this possible solution, setting c and d in main as plain doubles,referncing them in the function call with &, and using the * in the function logic, im stuck with this error - "Indirection requires pointer operand ('double' invalid)" – Jon Gardocki Nov 16 '19 at 09:20
  • First of all I overlooked that your function has float return type but it is not returning anything so be careful with that too, I just ran the code myself and it worked. I'm gonna try to find out reason for that error message and if I find anything I'll let you know. – Harun Tucakovic Nov 16 '19 at 09:31
  • 1
    @JonGardocki : This is a great answer, much better than the flawed one you have currently accepted (mine's quite good too ;-) ). The code provided compiles without error, so you need to consider how it differs from what you have. The error is not with this answer. – Clifford Nov 16 '19 at 09:53
4

You need to dereference c and d to assign them in myFunction():

*c = a/b;
*d = a*b;

Moreover from main, you need to create instances to which c and d refer to:

double c;
double d;

(you had created unitialised pointers with no instances).

Then in the the call:

pointerIntro(first, second, &c, &d);

The & address-of operator creates the reference arguments, referring to c and d in main().

It might be useful not to use the same symbol names c and d in main() and myFunction() to make it clearer what they are. For example:

void myFunction(double a, double b, double* cptr, double* dptr )
{
    *cptr = a/b;
    *dptr = a*b;
}

Note also, a function that returns nothing should be declared void.

Clifford
  • 88,407
  • 13
  • 85
  • 165
1

A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 40;, a pointer (e.g. int *p = &a;) would simply hold the address where 40 is stored in memory.

If you need to access the value stored at the memory address pointed to by p, you dereference p using the unary '*' operator, e.g. int j = *p; will initialize j = 40).

If you want to obtain a variables address in memory, you use the unary '&' (address of) operator. If you need to pass a variable as a pointer, you simply provide the address of the variable as a parameter.

In your case that boils down to writing your function similar to:

void multdiv (double a, double b, double *c, double *d)
{
    *c = a / b;
    *d = a * b;
}

(note: you should ensure b != 0 before dividing a / b -- that is left to you)

In order to provide storage for the values you will take as input as well as the values you want to hold the results of the multiplication and division, you need four double values, e.g.

int main (void) {

    double a, b, c, d;          /* your doubles */

You then need to prompt the user for input and validate the user input by checking the return of the input function used, e.g.

    fputs ("enter two double values: ", stdout);        /* prompt */
    fflush (stdout);    /* flush stream (optional but recommended) */

    if (scanf ("%lf %lf", &a, &b) != 2) {   /* validate EVERY input */
        fputs ("error: invalid double values.\n", stderr);
        return 1;
    }

(bonus: Why is the '&' used before a and b with scanf above? See first full paragraph under DESCRIPTION in man 3 scanf)

All that remains is to call your function to perform the calculations and output the results, e.g.:

    multdiv (a, b, &c, &d);     /* calculate c, d */

    printf ("\nc = a / b  => %.2f\nd = a * b  => %.2f\n", c, d);

(note: as explained above the address of operator is used to pass the address of c and d as parameters)

Putting it altogether you could do:

#include <stdio.h>

void multdiv (double a, double b, double *c, double *d)
{
    *c = a / b;
    *d = a * b;
}

int main (void) {

    double a, b, c, d;          /* your doubles */

    fputs ("enter two double values: ", stdout);        /* prompt */
    fflush (stdout);    /* flush stream (optional but recommended) */

    if (scanf ("%lf %lf", &a, &b) != 2) {   /* validate EVERY input */
        fputs ("error: invalid double values.\n", stderr);
        return 1;
    }

    multdiv (a, b, &c, &d);     /* calculate c, d */

    printf ("\nc = a / b  => %.2f\nd = a * b  => %.2f\n", c, d);

    return 0;
}

Example Use/Output

$ ./bin/multdivbyptrs
enter two double values: 4.0 2.0

c = a / b  => 2.00
d = a * b  => 8.00

Look things over and let me know if you have questions. Once you digest that a pointer is simply a normal variable that holds the address where something else is stored as its value -- things will start to fall into place. No magic..

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

Here is the correct way to do it. The func() method

void func(double x,double y,double *z,double *w){
    printf("pass by value = %lf, %lf",x,y);
    printf("pass by reference = %lf, %lf",*z,*w);
}

The main() method

int main(void){
   double first,second,val1,val2;
   val1=3.1;
   val2=6.3;
   printf("Enter your first number\n");
   scanf("%lf", &first);
   printf("Enter your second number\n");
   scanf("%lf", &second);
   func(first,second,&val1,&val2);  
}
Tejas Lotlikar
  • 131
  • 1
  • 8
0
  1. It is perfectly valid. You can initialize and pass any number of pointer variables with their reference.

  2. This is also valid..when you pass the variable address, you should store it into a pointers

you have to do some changes in your code, You can assign directly a/b and a*b pointer variables *c & *d Then you have to read double number with %lf format argument.

#include <stdio.h>
#include <string.h>

void myFunction(double a, double b, double *c, double *d)
{
*c = a/b;   //change
*d = a*b;   //change
printf("%lf %lf",*c,*d);
return;
//printf statements
}



int main()
{
//first and second double hold the scanf inputs
double first;
double second;

//unsure here - to reference c and d as parameters in the function, do I simply declare unfilled double variables here?
double *c;
double *d;

printf("Enter your first number\n");
scanf("%lf", &first);   //change
printf("Enter your second number\n");
scanf("%lf", &second);  //change

//call the function, first and second by value, &c / &d by reference - correct?
myFunction(first, second, &c,&d);
}
Clifford
  • 88,407
  • 13
  • 85
  • 165
VJAYSLN
  • 473
  • 4
  • 12
  • With this code, I'm receiving a "Control reaches end of non-void function" error. in the function declaration. Any idea? – Jon Gardocki Nov 16 '19 at 09:26
  • Please change return type as `void` , since you don't need to return anything right?? – VJAYSLN Nov 16 '19 at 09:30
  • Correct. Thank you so much, VJAY - just need to work my way through each step but your solution played off mine which helped tremendously. Thank you. – Jon Gardocki Nov 16 '19 at 09:34
  • 1
    @JonGardocki caution this is not a complete answer and as it stands is seriously flawed. You need to change `c` and `d` in `main()` to _instances_ not _pointers_: `myFunction(first, second, &c,&d);` when `c` and `d` are already `double*` (and uninitialised at that). Consider other answers perhaps. – Clifford Nov 16 '19 at 09:45