Call by value in C - c

I'm new to programming and I am currently working on C.
I learned that C does not have call by reference. The programs that we write to pass the address of actual parameters to the formal parameters is also call by Value in C.
Correct me if I'm wrong.. However, I ran this program :
//Swapping of two numbers using functions.
#include
void swap(int *,int *);
void main()
{
int x,y;
printf ("Enter the values of x and y : ");
scanf("%d %d",&x,&y);
swap(x,y);
printf("The value of x = %d and y = %d",x,y);
}
void swap(int *a,int *b)
{
int temp;
temp=*b;
*b=*a;
*a=temp;
}
It compiles just fine.. however, I'm getting a Segmentation Fault in the Output.
It asks me the enter the value of X and Y and then gives, Segmentation fault..
Please help!!

you are sending an int to a function that expects int*, thus when you are dereferencing - temp=*b; you are trying to access memory you don't own -> segfault. Call swap like this: swap(&x,&y);

So close
swap(&x,&y);
You were not passing references (pointers)

To avoid similar segfaults at runtime, always compile with -Wall.
Actually, there is a way to pass-by-reference in C, just change two lines in your code like this:
#define swap(x,y) swap_impl__(&(x), &(y))
static void swap_impl__(int *a, int *b)
{
int temp;
temp=*b;
*b=*a;
*a=temp;
}
void main()
{
int x,y;
printf ("Enter the values of x and y : ");
scanf("%d %d",&x,&y);
swap(x,y);
printf("The value of x = %d and y = %d",x,y);
}

the call by value method of passing arguments to a function copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.
but here you are passing values
swap(x,y)
but taking it as address
void swap(int *a,int *b)
so it is looking for an address which passed by your variable.
for example, if you have passed something like
swap(x,y)
and
if we have x=100 and y=200, then it is assuming 100 and 200 to be addresses
and trying to access it will definitely give you error as they may not exist or having garbage value.

Related

Trouble in C program for getting output [duplicate]

This question already has answers here:
Parameter Passing in C - Pointers, Addresses, Aliases
(2 answers)
Closed 4 years ago.
This is a simple program
#include<stdio.h>
void get(int,int);
void main()
{
int a,b;
get(a,b);
printf("In main");
printf("%d",a);
}
void get(int m,int n)
{
printf("enter the value");
scanf("%d%d",&m,&n);
}
and I got an output is
enter the value
4
5
in main:
0
Why is the value of m in get() not assigned to a in main()? What's my mistake?
You're passing your main variables via value. Read about how you can pass by reference, here. scanf requires addresses of variables in order to modify them; so you need to pass their addresses like this:
get(&a, &b);
And you can modify your get() method like this:
void get(int* pM,int* pN) {
printf("enter the value");
scanf("%d%d, pM, pN);
}
Your scanf reads into function local variables which store the values you give as parameters to the function.
Their values are not visible in the variables you give as parameters to the function.
You probably want to use pointers to variables as parameters, then the read values can end up in the variables pointed to by those pointer-parameters.
This is basically happening due to scope of variables, since integers are passed by value and not by reference.
You need to return values of a and b for them to be present in main().
see more here
https://www.tutorialspoint.com/cprogramming/c_function_call_by_value.htm
#inlcude<stdio.h>
int get(int,int);
void main() {
int a,b;
a = get(a,b);
printf("In main");
printf("%d",a);
}
int get(int m,int n){
printf("enter the value");
scanf("%d%d,&m,&n);
return m;
}
Enter the value
10 20
In main
10
Also, read about indenting the code so that it's more readable.
Why is the value of m in get() not assigned to a in main()? What's my mistake?
First, you need to understand the concept of parameter passing in C.
[If you are not aware of formal and actual parameters, check this]
Technically, everything in C is pass-by-value. Here,
get(a,b);
you are passing the value of a and b variable to function get(). The value of actual parameter a and b will be copied to formal parameters m and n [in this case, the value of a and b variable is garbage since you have not initialized them]. Any modification to the value of formal parameters (m and n) in the calling function will not reflect in the actual parameters (a and b) because formal parameter storage is separate. Hence, the value of m in get() does not assigned to a in main().
Below part of the answer is based on the assumption that you are aware of the concept of pointers in C language. If not, I would suggest to pick choose a good C language book/tutorial and go through the concept of pointers.
C language provides a facility to pass a pointer to a function which is also pass-by-value only. It copies the value of the pointer, i.e. the address, to the function formal parameters and you can access the value stored at that address by dereferencing the pointer. Hence, any changes made in the value at the address passed will reflect in the calling function actual parameters.
So, you can do:
#include<stdio.h>
void get(int *, int *);
int main()
{
int a, b;
get(&a, &b);
printf("In main\n");
printf("a : %d, b = %d\n", a, b);
}
void get(int *m,int *n)
{
printf("Enter the value:\n");
scanf("%d%d", m, n); // m holds the address of a and n holds the address of b variable.
printf("Value entered:\n");
printf("%d %d\n", *m, *n); //dereferencing the pointer m and n
}

C - Function which takes 2 floats and returns their difference after the block using pointers

I'm trying to write a function which takes two generic floats (make it 'a' and 'b') and returns their difference assigned to the variables, so a=a-b and b=b-a.
It should print the values with 2 decimal places and it must work after I exit the block... What is wrong with my code?
#include <stdio.h>
float diff_abs (float *a, float *b) {
*a= *a-*b;
*b= *b-*a;
}
int main(void) {
float c, d;
scanf("%f", &c);
scanf("%f", &d);
printf("%.2f\n%.2f", diff_abs(&c, &d));
return 0;
}
I would appreciate your suggestions, thank you.
First, you are changing a value then using it to the next calculation so simplify change your function to:
void diff_abs (float *a, float *b) {
*a= *a-*b;
*b = -*a
}
Second, since you can't return multiple variables in a C function, one of the solution is to use void returning function but change variables while using pointers (like you're somehow doing)
Finally, since your function returns void you can't use it as floats in the printf function so just use c and d
like this:
printf("%.2f\n%.2f",c,d);
of course don't forget to call:
diff_abs(&c, &d)
before trying to print
you can refer to this topic for returning multiple variables in C

how to pass a condition as parameter to function in C?

I have created an array of function pointers to swap two variables.
pointer pointing to these functions namely: swap1, swap2. swap3 and swap4.
swap2 is swaping using pointer passed as arguments.
but while declaring the function pointer, only int and int are passed as arguments. after compiling this causes many warnings.
so do we have a better way of passing the argument, where we put condition in function call itself.
code is given below.
#include <stdio.h>
int swap1(int ,int );
int swap2(int* ,int* );
int swap3(int ,int );
int swap4(int, int);
int swap1(int a,int b)
{
int temp=a;
a=b;
b=temp;
printf("swapped with 3rd variable :%d, %d\n", a,b);
}
int swap2(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
printf("swapped with pointer :%d, %d\n", *a,*b);
}
int swap3(int a,int b)
{
a+=b;
b=a-b;
a-=b;
printf("swapped with 2 variable :%d, %d\n", a,b);
}
int swap4(int a,int b)
{
a=a^b;
b=a^b;
a=a^b;
printf("swapped with bitwise operation :%d, %d\n", a,b);
}
int main()
{
int ch;
int a=3;
int b=4;
printf("enter the option from 0 to 3\n");
scanf("%d",&ch);
int (*swap[4])(int, int) ={swap1,swap2,swap3,swap4};// function pointer
/*can we pass something like int(*swap[4]( condition statement for 'pointer to variable' or 'variable')*/
if (ch==1)// at '1' location, swap2 is called.
{
(*swap[ch])(&a,&b);//passing the addresses
}
else
{
(*swap[ch])(a,b);
}
return 0;
}
some warnings are as follows.
at line 36 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
Well yes. There are a number of problems with your code, but I'll focus on the ones to which the warnings you presented pertain. You declare swap as an array of four pointers to functions that accept two int arguments and return an int:
int (*swap[4])(int, int)
Your function swap2() is not such a function, so a pointer to it is not of the correct type to be a member of the array. Your compiler might do you a better favor by rejecting the code altogether instead of merely emitting warnings.
Having entered a pointer to swap2() into the array anyway, over the compiler's warnings, how do you suppose the program could call that function correctly via the pointer? The type of the pointer requires function arguments to be ints; your compiler again performs the dubious service of accepting your code with only warnings instead of rejecting it.
Since the arguments in fact provided are the correct type, it might actually work on systems and under conditions where the representations of int and int * are compatible. That is no excuse, however, for writing such code.
Because pointers and ints are unchanged by the default argument promotions, one alternative would be to omit the prototype from your array declaration:
int (*swap[4])() = {swap1,swap2,swap3,swap4};
That says that each pointer points to a function that returns int and accepts a fixed but unspecified number of arguments of unspecified types. At the point of the call, the actual arguments will be subject to the default argument promotions, but that is not a problem in this case. This option does prevent the compiler from performing type checking on the arguments, but in fact you cannot do this correctly otherwise.
Your compiler might still warn about this, or could be induced to warn about it with the right options, but the resulting code nevertheless conforms and does the right thing, in the sense that it calls the pointed-to functions with the correct arguments.
To deal with the warnings first: You declare an array of functions which take int parameters. This means that swap2 is incompatible with the type of element for the array you put it in. This will generate a diagnostic.
Furthermore, when you call one of the functions in the array, the same array declaration tells the compiler that the parameters need to be ints not pointers to int. You get two diagnostics here, one for each parameter.
To fix the above all your functions need to have compatible prototypes with the element type of the array. Should it be int or int*? This brings us to the other problem.
C function arguments are always pass by value. This means that the argument is copied from the variable onto the stack (or into the argument register depending on the calling convention and argument count - for the rest of this post, I'll assume arguments are placed on the stack for simplicity's sake). If it's a literal, the literal value is put on the stack. If the values on the stack are changed by the callee no attempt is made by the caller, after the function returns, to put the new values back in the variables. The arguments are simply thrown away.
Therefore, in C, if you want to do the equivalent of call by reference, you need to pass pointers to the variables you use as arguments as per swap2. All your functions and the array should therefore use int*. Obviously, that makes one of swap1 and swap2 redundant.
The correct array definition is
int (*swap[4])(int*, int*) = {swap1, swap2, swap3, swap4};
and the definition of each function should be modified to take int* parameters. I'd resist the temptation to use int (*swap[4])() simply because it circumvents type safety. You could easily forget the & in front of an int argument when the called function is expecting a pointer which could be disastrous - the best case scenario when you do that is a seg fault.
The others have done great work explaining what the problems are. You should definitely read them first.
I wanted to actually show you a working solution for that sort of problem.
Consider the following (working) simple program :
// main.c
#include <stdio.h>
void swap1(int* aPtr, int* bPtr) {
printf("swap1 has been called.\n");
int tmp = *aPtr;
*aPtr = *bPtr;
*bPtr = tmp;
}
void swap2(int* aPtr, int* bPtr) {
printf("swap2 has been called.\n");
*aPtr += *bPtr;
*bPtr = *aPtr - *bPtr;
*aPtr -= *bPtr;
}
int main() {
int a = 1, b = 2;
printf("a is now %d, and b is %d\n\n", a, b);
// Declare and set the function table
void (*swapTbl[2])(int*, int*) = {&swap1, &swap2};
// Ask for a choice
int choice;
printf("Which swap algorithm to use? (specify '1' or '2')\n>>> ");
scanf("%d", &choice);
printf("\n");
// Swap a and b using the right function
swapTbl[choice - 1](&a, &b);
// Print the values of a and b
printf("a is now %d, and b is %d\n\n", a, b);
return 0;
}
First of, if we try to compile and execute it:
$ gcc main.c && ./a.out
a is now 1, and b is 2
Which swap algorithm to use? (specify '1' or '2')
>>> 2
swap2 has been called.
a is now 2, and b is 1
As myself and others mentioned in answers and in the comments, your functions should all have the same prototype. That means, they must take the same arguments and return the same type. I assumed you actually wanted to make a and b change, so I opted for int*, int* arguments. See #JeremyP 's answer for an explanation of why.

C - multiple “outputs" from a function

I must be doing something monumentally stupid here but I can’t figure out what. If I printf the values within the foo function, it displays the correct values.
But if I try to print them in main, I get nonsense results (0 and 1, respectively).
void foo(int a, int b){
a = 1;
b = 2;
}
int main(void){
int a;
int b;
foo(a, b);
printf(“%i \n”, a);
printf(“%i \n”, b);
}
You need to change your foo method to take pointers:
void foo(int *a, int *b)
{
*a = 1;
*b = 2;
}
Then your call to foo must change to:
foo(&a, &b);
This basically says: Pass the address of 'a' and 'b' to the function foo, so it has the ability to change their values.
Your previous code just sent a copy of 'a' and 'b' into foo, so the change made in foo had no effect on your original two variables.
In your program you are trying to change the local variables in your function without passing their adresses.It may give you error in your code.If you pass the addresses to the function you can change the values of variables.
foo(&a, &b);//Passing addresses to the function.
void foo(int *a, int *b)//accessing value at that address
The above process is called 'call by reference'.

How do you pass the result from one function into another function?

Please consider this code example:
int func1(int,int); // function 1 prototype
int func2(int); // function 2 prototype
I am trying to send the output of function-1 as the input to function-2, but have been unsuccessful till now.
If someone could please explain the same with an example, that would be great.
Also, is the same possible with respect to Pass-by value and Pass-by-reference?
How about simply
int x = func2(func1(1,2));
int a = func2(func1(7, 9));
Just pass the expression containing the call to func1 as the argument to func2.
You could do this by nesting functions:
func2( func1(42, 24) );
Nesting lots of functions can easily become hard to read, so for more readability you could store the return value of func1 in a temporary variable:
int tmp = func1(42, 24);
func2(tmp);
Regarding your question about pass-by-reference vs. pass-by-value: In all these function calls, the parameters are passed by value. That's because the function signatures define the parameters as int, not int *
As the other answers said: func2( func1(1, 2) );
In C you can only pass parameters by value. Now having said that, passing the value of a pointer that points to the memory you want to change achieves the same effect as passing by reference.
int foo(int *x){
printf("The address that you passed to the function is: %x", x);
printf("The value is: %d", *x);
*x = 10;
}
int mem;
foo(&mem); //print the address of mem
in C++, you can pass by refference.
int foo(int &x){
printf("The address that you passed to the function is: %x", &x);
printf("The value is: %d", x);
x = 10;
}
int mem;
foo(mem); //print the address of mem

Resources