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
}
Related
This question already has an answer here:
Confusion about the fact that uninitialized pointer points to anywhere
(1 answer)
Closed 4 years ago.
I'm going to take data structures course this year, so I decided to renew my knowledge about C by doing some simple tasks about pointers in C, and I have noticed one thing about passing pointers to functions, that I can't really understand.
Let's say we have a function:
void assignValueTen(int *var){
*var=10;
}
We can call this function from main like this:
int main( void ){
int x;
assignValueTen(&x);
printf("The value of x is %d.\n",x);
return 0;
}
The output of this would be:
The value of x is 10.
We can also call this function like this:
int main( void ){
int x, *y;
y=&x;
assignValueTen(y);
printf("The value of x is %d.\n",x);
return 0;
}
The output of this would also be:
The value of x is 10.
However, the statement below does not work as expected:
int main( void ){
int *x;
assignValueTen(x);
printf("The value of x is %d.\n",*x);
return 0;
}
Output of the code above is:
Process exited after 6.723 seconds with return value 3221225477
So, why does the code compile but not work as expected?
Is it because the pointer is not yet assigned to any address before in the last example?
Can somebody explain why this is happening in a little more detail?
Thanks a lot!
The one that does not work is because x is not assigned any value in particular. The assignment in the function is assigning wherever that uninitialized variable happens to point and that is very unlikely to be a valid address (as the hardware sees things) and even if it is valid (again according to the hardware) it is not somewhere you should be writing to (because the address would 'belong' to something other than the code you are running in main).
You should only access addresses you have reason to know are valid (your assignValueTen function has such as an implicit requirement), C does not really have a way to enforce such requirement contracts though some other languages do.
Because when you do:
int main( void ){
int x;
assignValueTen(&x);
printf("The value of x is %d.\n",x);
return 0;
}
or:
int main( void ){
int x, *y;
y=&x;
assignValueTen(y);
printf("The value of x is %d.\n",x);
return 0;
}
you're always printing an int , while in the last example you're trying to print a pointer to an int, or at least that's the way i see it.
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.
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.
I just started learning functions and passing the parameters. so i am kind of new to this. Here, in the following programming, i am changing the values of a[] which is a formal parameter. even though, the sort function is not returning anything. how are the elements in numberArray[] are getting sorted even though the sort function just dealing with the formal parameters?
#include<stdio.h>
void sort(int[],int);
int main(void)
{
int n;
printf("enter the number of elements : ");
scanf("%d",&n);
int numberArray[n];
printf("enter %d numbers :\n",n);
for(int i=0;i<n;i++)
scanf("%d",&numberArray[i]);
sort(numberArray,n);
printf("sorted list of numbers are :\n");
for(int i=0;i<n;i++)
printf("%d\n",numberArray[i]);
return 0;
}
void sort(int a[],int n)
{
int i,j,temp;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]>a[j])
{
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
}
}
}
I would like to compare the above program with a simple program as follows.
#include<stdio.h>
void nothing(int);
int main(void)
{
int a;
printf("enter the value : ");
scanf("%d",&a);
nothing(a);
printf(" a = %d",a);
return 0;
}
void nothing(int b)
{
b=b+2;
}
In this program, the value of a is not changing. Why?
In C array parameters to functions are a fiction. Arrays don't get passed to functions; the parameter is treated as a pointer.
So in your example a is really an int*.
Personally, I think that function parameters declared as arrays is almost always a bad idea, since it doesn't model what is really being passed to the function. Until you understand what is really happening, it can cause confusion of the sort you ran into. It also commonly causes problems with people who try to obtain he size of the array passed to a function using the sizeof operator - that doesn't work since sizeof will return the size of a pointer type, not the actual array type.
The one situation where I think array formal arguments might make sense is with multi-dimension arrays, where the pointer arithmetic can be helpful.
Note that C99 introduced variable length arrays (VLAs) which can change much of this. VLAs are different animals, but because support for them came rather late (even after C99 was standardized, it took a while for may implementations to support them properly). This answer doesn't necessarily apply to passing VLAs as arguments to functions.
C passes by value ie
void nothing(int b) {
b=b+2;
}
is getting a copy of the integer. If you want to see the int change you need to pass it's address ie
void nothing(int *b) {
*b = *b + 2;
}
You pass the address as following
nothing(&a);
In the program you reference this function...
void sort(int a[],int n)
is taking a pointer to an array of integers as it's first argument so any change to it in the function changes the actual memory it points to
#include <stdio.h>
void printaddr(int n)
{
printf("%p", &n);
}
int main()
{
int n;
scanf("%d",&n);
printf("%p \n", &n);
printaddr(n);
}
Address of variable n in main loop is printed : 0028FF0C , while in function printaddr its printed 0028FEF0 .
I want to know why is there difference in address and whether or not does that difference represent anything ?
The addresses are different because they are two different variables.
When you call a function, the function parameters are initialized with copies of the function argument values. If you changed n inside printaddr, it would have no effect on the value of n inside main.
The function gets a copy of the variable, because of pass-by-value semantics. So, it's actually a different variable. The addresses are different because the memory is different.
As a test, try changing n in printaddr and seeing if it changes in main. Hint, it won't.
You can pass a pointer to a function if you want to have access to the same chunk of memory.
To expand on what Arun A.S has mentioned:
You are calling the function:
void printaddr(int n)
and you caller is passing in n (by value) rather than &n (the address of n), so you are passing by value rather than reference.
When you pass by value the value is locally copied to the function, so the original value is not changed.
Once the function completes, the local copy of n is destroyed unless you return the value.
This is why if you change the value of n in that same function (without returning the value) it will not be the same value when you access the variable n from your main.
Because in
void printaddr(int n)
you are creating a new local variable n ( local to the function ) with a different address.
You could instead use a pointer like
void printaddr(int *n)
and call it as
printaddr(&n);
So, if you change your code to
#include<stdio.h>
void printaddr(int *n)
{
printf("%p", n);
}
int main()
{
int n;
scanf("%d",&n);
printf("%p \n", &n);
printaddr(&n);
}
You will get the same address. ( But please note that the n inside the function would just point to the address of the n from main() , it does not have the same address as it )