Parameter Passing Techniques in C

Thread Starter

Gajyamadake

Joined Oct 9, 2019
276
I am trying to written code that does not return any value but pass the integer value

I have created the function that pass the two argument and perform the addition

Code:
#include<stdio.h>

int main(void)
{    
   addition (2, 5);

    return 0;
}

void addition (int a, int b)
{
    int c = a + b ;
  
    printf(" c = %d ", c);
warning: conflicting types for 'addition'
void addition (int a, int b)
^~~~~~~~
note: previous implicit declaration of 'addition' was here
addition (2, 5);
^~~~~~~~

c = 7

I don't understand what type of warning is this and why it does generates ?
 

BobTPH

Joined Jun 5, 2013
2,255
You have referred to the function before declaring it. The complier made an assumption about the arguments. The you declare the function and it thinks the new definition is different.

Move the function im front of “main” in your program and it will compile.

Bob
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
276
Didn't supply a function prototype ?

https://www.programiz.com/c-programming/c-user-defined-functions

Regards, Dana.
Its important We need to declare prototype function
Is this code is example of call by value ?
I think yes because we are passing value
Code:
#include<stdio.h>

void addition (int a, int b);  //prototype function
int main(void)
{  
   addition (2, 5);
    return 0;
}
void addition (int a, int b)
{
    int c = a + b ;
    printf(" c = %d ", c);
  
}
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
276
All C arguments are passed by value.

Bob
I thought arguments get passed by value and/or reference ?

Regards, Dana.
I wrote program to pass the arguments by value and/or reference
Code:
#include<stdio.h>

void addition (int *a, int *b);
int main(void)
{
   addition (2, 5);
    return 0;
}
void addition (int *a, int *b)
{
    int c = a + b ;
    printf(" c = %d ", c);

}
Compiler gives warning

In function 'main':
:7:14: warning: passing argument 1 of 'addition' makes pointer from integer without a cast [-Wint-conversion]
addition (2, 5);
^
:3:6: note: expected 'int *' but argument is of type 'int'
void addition (int *a, int *b);
^~~~~~~~
:7:17: warning: passing argument 2 of 'addition' makes pointer from integer without a cast [-Wint-conversion]
addition (2, 5);
^
:3:6: note: expected 'int *' but argument is of type 'int'
void addition (int *a, int *b);
^~~~~~~~
: In function 'addition':
:14:15: error: invalid operands to binary + (have 'int *' and 'int *')
int c = a + b ;
^

Output c = 7

I am confuse in code How to pass the arguments by reference?
 

BobTPH

Joined Jun 5, 2013
2,255
As I said before ALL arguments in C are passed by value.

What you have done is pass a pointer by value. Inside the function you are using the pointer as if it was an int passed by reference. It is not.

In C++ you can pass by reference, but not in C.

To refer to the int pointed to by the pointer in your code, you must put a * in front of it. For example:

int c = *a + * b;

Bob
 

Papabravo

Joined Feb 24, 2006
12,898
When you pass a pointer to a function you are passing the "value" of the pointer. All arguments are passed by value.
In your example you need to do the following:

a = 2; b =5;
addition (&a, &b) ;
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
276
To refer to the int pointed to by the pointer in your code, you must put a * in front of it. For example:

int c = *a + * b;

Bob
Does it pass value 2 and 5 by the address of a and b?

Code:
#include<stdio.h>
void addition (int *a, int *b);
int main(void)
{
   addition (2, 5);
    return 0;
}
void addition (int *a, int *b)
{
    int c = *a + *b ;
   
    printf(" c = %d ", c);
}
 

Thread Starter

Gajyamadake

Joined Oct 9, 2019
276
When you pass a pointer to a function you are passing the "value" of the pointer. All arguments are passed by value.
In your example you need to do the following:

a = 2; b =5;
addition (&a, &b) ;
call by reference
Code:
#include<stdio.h>
void addition (int *a, int *b);
int main(void)
{
    int a = 2; int b =5;
    addition (&a, &b) ;
 
    return 0;
}
void addition (int *a, int *b)
{
    int c = *a + *b ;
  
    printf(" c = %d ", c);
}
 

MrSoftware

Joined Oct 29, 2013
1,674
Play with these examples until you understand them. Also open the memory watch in your debugger and watch what is stored in the memory addresses for each variable.

Code:
#include <stdio.h>

void addition_by_ref(int *a, int *b)
{
    printf("The values passed were pointers, addresses of the variables: %lu, %lu\n", (long int)a, (long int)b); // Cast as int to suppress compiler warnings, we actually want to print the addresses
    printf("To add them we have to dereference them: %i + %i = %i\n", *a, *b, (*a+*b));
}

void addition_by_value(int a, int b)
{
    printf("The values passed were integers: %i, %i\n", a, b);
    printf("To add them we add them directly: %i + %i = %i\n", a, b, (a+b));
}



int main()
{
    int intA = 1;
    int intB = 2;
    addition_by_ref(&intA, &intB);
    printf("-----\n");
    addition_by_value(intA, intB);

    return 0;
}

Code:
/******************************************************************************

                            Online C Compiler.
                Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/

#include <stdio.h>

void passvalue(int a, int b)
{
    printf("Entering passvalue()\n");
    printf("a and b are: %i, %i\n", a, b);
    printf("Lets change them to be 3 and 4\n");
    a = 3;
    b = 4;
    printf("Now a and b are: %i, %i\n", a, b);
}

void passaddress(int *a, int *b)
{
    printf("Entering passaddress()\n");
    printf("After dereferencing the address to a and b, we get the values: %i, %i\n", *a, *b);
    printf("Because we have the addresses, we will change their values to 3 and 4\n");
    *a = 3;
    *b = 4;
    printf("Now a and b are: %i, %i\n", *a, *b);
}



int main()
{
    int intA = 1;
    int intB = 2;
   
    printf("Before passvalue, intA and intB are: %i, %i\n", intA, intB);
    passvalue(intA, intB);
    printf("After passvalue, intA and intB are: %i, %i\n", intA, intB);
   
    printf("--------\n");

    printf("Before passaddress(), intA and intB are: %i, %i\n", intA, intB);
    passaddress(&intA, &intB);
    printf("After passaddress(), intA and intB are: %i, %i\n", intA, intB);
   
    return 0;
}
 

MrSoftware

Joined Oct 29, 2013
1,674
No, you cannot pass integer constants to a function expecting pointers to integers.

Bob
Just to clarify; In C you CAN pass an int in place of an address (pointer), but you won't like the results. The compiler will let you do it, and in the example below because I've declared my variables as long int, which just happen to be the same size as pointers on this particular platform, the compiler doesn't even give me a warning. However you can see that it crashes (segmentation fault) when it tries to access memory that it shouldn't at addresses "1" and "2":

What the cast to long int* is doing is telling the compiler "trust me I know what I'm doing, the value held by this integer is really the memory address of a variable of type long int", and the compiler says "OK!" and lets you do it. But at run time when the process tries to access memory at addresses "1" and "2", the operating system (in this case) says "oh no you don't!" and crashes your process. On a smaller processor that isn't running an operating system, your results are likely to be a bit more random.

Code:
#include <stdio.h>

void addition(long int *a, long int *b)
{
    printf("%lu + %lu = %lu\n", *a, *b, (*a+*b));
}

int main()
{
    long int intA = 1;
    long int intB = 2;
  
    // This will work properly
    printf("Addition the correct way: ");
    addition(&intA, &intB);
  
    // This is incorrect and will probably crash due to accessing memory you shouldn't,
    // but due to the cast the compiler will let you do it
    printf("Addition the INCORRECT way: ");fflush(stdout); // Flush output before it crashes
    addition((long int*)intA, (long int*)intB);

    return 0;
}
upload_2019-10-15_9-58-57.png
 

BobTPH

Joined Jun 5, 2013
2,255
Just to clarify; In C you CAN pass an int in place of an address (pointer), but you won't like the results.
No, it allows you to cast an int to a pointer, then pass that pointer. If you simply tried to pass an int it will (should) be flagged by the compiler.

Bob
 

MrSoftware

Joined Oct 29, 2013
1,674
I think we're saying the same thing. Casting an int to a pointer is still passing the value of the int. i.e. if a = 5 and you pass (int*)a, you're still passing "5".
 

BobTPH

Joined Jun 5, 2013
2,255
We are, but there is a subtle distinction. I see the error as being in the cast, not in passing the result of the expression, which is indeed the correct type (long int*)

The result is the same.

If you tried to do:

addition(123L, 456L)

The compiler would flag an error for trying to pass the wrong type to the function.

Bob
 

MrSoftware

Joined Oct 29, 2013
1,674
Using gcc as an example, passing the wrong argument type without a cast is merely a warning as shown below. Which is actually an excellent example of why you should always resolve warnings! You can use compiler flags to turn it into an error, which is a good idea especially for the OP while they're learning:

Code:
#include <stdio.h>
void addition(long int *a, long int *b)
{
    printf("%lu + %lu = %lu\n", *a, *b, (*a+*b));
}
int main()
{
    long int intA = 1;
    long int intB = 2;
    addition(1L, 2L);
}
upload_2019-10-15_16-56-53.png

Below using the -Werror compiler flag to turn all warnings into error. The flag -pedantic-errors would give similar results, maybe other flags too:

upload_2019-10-15_16-57-45.png
 
Top