This question already has answers here:
What does ** do in C language? [duplicate]
(14 answers)
Closed 1 year ago.
I'm trying to understand purpose and how it's works double pointer in this code.
Why we use **p in the declaring function but inside the function we used *p?
void allocate(int** p)
{
*p = (int*)malloc(sizeof(int));
}
int main()
{
int *p = NULL;
allocate(&p);
*p = 42;
}
The function's parameter p has type pointer-to-pointer to int, i.e. int **. So referring to p refers to an object of that type.
The expression *p dereferences p giving you an expression (which is also an lvalue) of type int *. This matches the type of p in the main function, and actually refers to that object. This allows us, inside the function allocate, to modify the value of p in main to contain the address of a dynamically allocated block of memory.
To change the original pointer p declared within the function main in function allocate you need to pass it by reference. Otherwise the function will deal with a copy of the value of the original pointer p and changing the copy will not influence on the value stored in the original pointer.
In C passing by reference means passing an object indirectly through a pointer to it. So dereferencing the pointer you will get an access to the original object.
Consider the following demonstrative program.
#include <stdio.h>
void f( int x )
{
x = 20;
}
int main(void)
{
int x = 10;
printf( "Before calling the function d c = %d\n", x );
f( x );
printf( "After calling the function d c = %d\n", x );
return 0;
}
Its output is
Before calling the function d c = 10
After calling the function d c = 10
As you can see the original variable x was not changed after calling the function f because the variable is passed by value to the function.
Now consider the following program.
#include <stdio.h>
void f( int *px )
{
*px = 20;
}
int main(void)
{
int x = 10;
printf( "Before calling the function d c = %d\n", x );
f( &x );
printf( "After calling the function d c = %d\n", x );
return 0;
}
At this time the program output is
Before calling the function d c = 10
After calling the function d c = 20
As the variable x was passed by reference then dereferencing the pointer
px
*px = 20;
you get a direct access to the original variable x through the pointer.
So if you want to change a pointer itself then passing it by reference means passing a pointer to the pointer the same way as it was done in the function above only now the type of the original variable p is int * instead of int.
That is if you have a declaration like this
T x;
where T is some type (as for example int or int *) then to pass the variable by reference you need to use a function argument expression like &x. that will have the type T *. If T is equivalent to the type int * then you need to use an argument expression of the type int **.
Related
Hello everyone so I have been learning C and I came across this example and I don't really find the logic behind. this is not a technical question regarding code I was looking more for an explanation.
this is the code
#include <stdio.h>
void set_array(int array[4]);
void set_int(int x);
int main(void)
{
int a = 10;
int b[4] = {0, 1, 2, 3};
set_int(a);
set_array(b);
printf("%d %d\n", a, b[0]);
}
void set_array(int array[4])
{
array[0] = 22;
}
void set_int(int x)
{
x = 22;
}
the output is 10 22
basically my question is why does the 22 that is passed from the set_array function rewrites the 0 on the b array and actually prints but the 22 that is passed from the set_int function doesn't get passed nor printed.
Thank you all!
In C passing by reference means passing an object indirectly through a pointer to it. If you will pass an object directly to a function then the function will deal with a copy of the value of the object.
Compare two function calls in this demonstrative program.
#include <stdio.h>
void f( int x )
{
x = 10;
}
void g( int *x )
{
*x = 10;
}
int main(void)
{
int x = 0;
printf( "Before call f: x = %d\n", x );
f( x );
printf( "After call f: x = %d\n", x );
putchar( '\n' );
printf( "Before call g: x = %d\n", x );
g( &x );
printf( "After call g: x = %d\n", x );
return 0;
}
The program output is
Before call f: x = 0
After call f: x = 0
Before call g: x = 0
After call g: x = 10
That is we passed to the function f the object x directly. So the function deals with a copy of the object x. Changing the copy does not influence on the original object x declared in main.
As for the function g then it got an access to the object x indirectly through a pointer to it. So changing the pointed object we changed the object x declared in main.
As for arrays then when an array is passed to a function it is implicitly converted to pointer to its first element. So the function in fact gets elements of the array by reference through this pointer. Using the pointer and the pointer arithmetic we can change any element of the array.
This function declaration
void set_array(int array[4]);
is equivalent to the following declaration
void set_array(int array[]);
and the both declarations are adjusted by the compiler to the declaration
void set_array(int *array);
So the function deals with a pointer - the pointer to the first element of the array used as an argument of the function call.
The call of the function set_array in your program
set_array(b);
is equivalent to the following call
set_array( &b[0] );
because arrays used in expressions as for example as a function argument expression are implicitly converted to pointers to their first elements.
C functions, when receiving parameters other than arrays and pointers (arryays are actually translated to pointers) don't update the source value because they created a copy of the value passed by the parameter.
Should your function be:
void set_int(int *x)
{
x = 22;
}
Then you're working with the source variable. But since you didn't declare a pointer, but a variable, you'd have to call it like this:
set_int(&a);
To ensure you're passing a's memory reference, rather than it's content.
Before I start I want to tell you I am learning to program.
What is the difference between Passing the variable to function and passing an array to the function in C?
When we pass a variable to function we are just passing the value of function. But when we pass an array we are passing somehow a pointer because when we do some changes on an array inside a function, actual array gets changed.
In order to make my question clear I am attaching code which will explain what I am asking-
Code 1:
//Passing variable to function
#include<stdio.h>
void swap(int x, int y);
int main(void)
{
//Nothing is happening to real values of variables
int x, y;
x = 1;
y = 2;
swap(x, y);
printf("%d = x \n %d = y", x, y);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
Code 2:
//Here you can see the values of arrays are swapped.
#include<stdio.h>
void swap(int arr[]);
int main(void)
{
int idx, array[2];
for(idx = 0; idx < 2; idx++ )
{
scanf("%d", &array[idx]);
}
swap(array);
for(idx = 0; idx < 2; idx++, printf("\n"))
{
printf("%d", array[idx]);
}
}
void swap(int arr[])
{
int temp;
temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
Maybe my question is still unclear but I just want to know why the values of the array gets changed in main function as when we call the function we are just passing a function value of that variable.
In the both cases when a variable as you are saying is passed to a function or an array is passed to a function there is passed a value.
But in the first case there is passed the value of the variable while in the second case there is passed the value of the pointer to first element of an array.
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
So having a pointer to an object you can change the pointed object.
Let's assume that you have two functions.
void f( int x )
{
x = 10;
}
and
void g( int *px )
{
*px = 10;
}
and their calls
int n = 0;
f( n );
g( &n );
You can imagine the function definitions and their calls the following way
int n = 0;
f( n );
g( &n );
//...
void f( /* int x */ )
{
int x = n;
x = 10;
}
void g( /* int *px */ )
{
int *px = &n;
*px = 10;
}
That is the both functions deal with copies of values of the expressions used as function arguments. But in case of the function g as the function gets the value of the address of the pointed object n you can change the pointed object n using the pointer (address).
In the terms of C passing an object to a function indirectly through a pointer to the object is called passing by reference.
From the C Standard
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
Pay attention to that a function declaration like this
void f( int a[], size_t n );
is equivalent to the following declaration
void f( int *a, size_t n );
And the both declare the same one function.
If you have an array as for example
#define N 10
//...
int a[N];
then it is passed to the function like
f( a, N );
then as it is followed form the first quote from the C Standard the array designator is converted to pointer to its first element. And having this pointer in the function you can change any element of the array because each element of the array in fact is passed by reference. Using the pointer arithmetic you can change any element of the pointed array. For example
void f( int *a, size_t n )
{
for ( int i = 0; i < n; i++ )
{
a[i] = i;
// that is the same as
// *( a + i ) = i;
}
}
When you pass an array, you are actually passing the base address of the same, which is a pointer to the first array element in the memory. It is inherently a call by reference, so you don't need to explicitly use a reference or & while passing into your swap function. arr decays to &(arr[0]).
On the other hand, variables are not by default passed by value, and you need to explicitly use a & to pass them by reference to get their values swapped in their memory locations and not just specific to the scope of the swap function.
What is the difference between Passing the variable to function and passing an array to the function in C?
You cannot pass an array as it is to a function. The C syntax does not allow that. When you provide the identifier of an array as argument it decays to a pointer to the first element of the array - so you pass the array by reference to its first element.
If the relative parameter of the function is of the matching pointer type, here int * or int a[], this is permissible.
Instead when providing a variable as argument you pass it by value. Means you do not access the variable provided as argument in the function itself. Rather the value is copied into a local variable of the function.
If you want to change the value of the variable passed itself, you need to use the & ampersand operator to gather the address of the variable itself. This is only permissible if the relative parameter is of matching pointer type as above.
Thus, In the first example you do not swap the values of x and y in main(). You only change x and y inside of swap() which is pretty useless.
If you want to swap xand y in main you need to define swap() as:
void swap(int* x, int* y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
and call swap() like:
swap(&x, &y);
I suggest you to learn more about pointers.
You are not passing the array as copy. It is only a pointer pointing to the address where the first element is in memory.
When passing an array as a parameter, this
void arraytest(int a[])
means exactly the same as
void arraytest(int *a)
so you are modifying the values in main. However in C function arguments are always passed by value. In case of an array (variable), while passed as a function argument, it decays to the pointer to the first element of the array. The pointer is then passed-by-value, as usual.
An array is a special variable. When you pass a regular variable to a function as an argument, its value is copied to a local variable pertaining to the function.
When you pass an array to a function as an argument, the address of the first element of the array is copied to a local variable pertaining to the function.
That is basically the difference between passing a regular variable and passing an array to a function.
There is one issue with your perception though. If you want to modify a regular variable to be passed to a function, then you need to pass its address to the function, thus the function should take a pointer type. So just use the pointer notation, i.e int *p as opposed to int p[], even though, they are equivalent as function parameters.
Your code should look like this:
#include<stdio.h>
void swap(int *x, int *y);
int main(void)
{
int x, y;
x = 1;
y = 2;
swap(&x, &y);
printf("%d = x \n %d = y", x, y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
This question already has answers here:
Passing an array as an argument to a function in C
(11 answers)
Closed 1 year ago.
An element of an array can be changed like this.
#include <stdio.h>
void func(int a[]){
a[0] = 56;
}
int main()
{
int a[1]={34};
func(a);
printf("%d" ,a[0]);
return 0;
}
But when the array is replaced by just 'int a'; it remains unchanged. Or in other words, to change value of 'int a' from outside main(), pointers are required. What is the reasoning behind this? Why can an array be changed from a function without pointers but a simple 'int a' requires a pointer for modification?
To change an object in a function you need to pass it by reference. Otherwise the function will deal with a copy of the value of the passed object.
In C passing by reference means passing an object indirectly through a pointer to it.
This function declaration
void func(int a[]){
a[0] = 56;
}
is equivalent to
void func(int *a){
a[0] = 56;
}
due to adjusting by the compiler a parameter having an array type to pointer type to the array element type.
So in the above function elements of the array are passed in fact by reference. That is having a pointer to the first element of an array and the pointer arithmetic you can change any element of the array.
To change the same way a scalar object you need to pass it through a pointer to it.
To make the difference visible then if you have for example a function like
void func( int value )
{
value = 56;
}
And in main you have
int x;
func( x );
then the function call may be imagined the following way
void func( /*int value */ )
{
int value = x;
value = 56;
}
As you can see it is the local variable value initialized by the value of the variable x that is changed.
On the other have if you have a function like
void func( int value[] )
{
value[0] = 56;
}
and in main you have
int a[1];
func( a );
then the function call may be imagined the following way
func( &a[0] );
void func( /* int value[] */ )
{
int *value = &a[0];
value[0] = 56;
}
This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 2 years ago.
I'm new to C, sorry if my question sound dumb.
I see some function takes a "double" pointer as parameter, for example:
int main(int argc, char **argv)
{
...
}
I can understand the need for a double pointer such as argv, since argv is the pointer to the first element of argument array whose element is also a pointer to a char type. double pointer is needed in this case.
But for some functions like:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
I don't understand why a double point is needed, since there is no array element involved, and I think getaddrinfo calls malloc internally, so it might be a reason to use double pointer, but we can have sth like this:
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char *ptr)
{
ptr = malloc(10);
}
so the parameter is a single pointer char * ptr, no char **ptr is needed?
Passing a pointer, or address of an object allows the value stored at that location in memory to be changed by the function, so when the function returns, the information stored at that address now contains updated values. Likewise if a function argument accepts a pointer variable, and the pointer variable is to be changed, the address to that pointer must be passed, thus requiring the function prototype to be a pointer-to-pointer.
Addressing your question may illustrate: getaddrinfo question: I don't understand why a double point is needed, since there is no array element involved
Usage for this struct is typically:
struct addrinfo *result;//pointer variable
getaddrinfo("hostname", "servicename", NULL, &result);
// |_Passing address of a pointer variable.
// thus requiring prototype to accommodate
So as explained, for the function to receive updated struct information, it needs to send the address of the pointer variable, requiring it to be a double pointer:
int getaddrinfo(const char *host, ..., struct addrinfo **result);
Your code is incorrect. ptr is local to the scope of test. A pointer is just a number representing a memory address. You probably wouldn't expect test in the following code to affect the value of number_main, right?
int main()
{
int number_main;
test(number_main);
printf("%d\n", number_main);
}
void test(int number_main)
{
number_main = 10;
}
Maybe it helps if you internalize char * as some fictional type you'll call number_that_represents_memory_address, which you then think about as no different than int in this case?
This function
void test(char *ptr)
{
ptr = malloc(10);
}
that shall be declared before its usage in main deals with a copy of the value of the passed argument in main
char *ptr_main;
test(ptr_main);
You can imagine the function call and the function definition the following way
char *ptr_main;
test(ptr_main);
//...
void test( /* char *ptr */ )
{
char *ptr = ptr_main;
ptr = malloc(10);
}
So as you can see within the function it is the local variable ptr that is changed. The argument ptr_main that was not initialized in main and has indeterminate value stays unchanged.
To change the original pointer ptr_main you have to pass it to the function by reference.
In C the mechanism of passing by reference is implemented by passing an object indirectly through a pointer to it.
From the C Standard (6.2.5 Types)
— A pointer type may be derived from a function type or an object
type, called the referenced type. A pointer type describes an object
whose value provides a reference to an entity of the referenced
type. A pointer type derived from the referenced type T is sometimes
called ‘‘pointer to T’’. The construction of a pointer type from a
referenced type is called ‘‘pointer type derivation’’. A pointer type
is a complete object type.
So the function definition should look like
void test( char **ptr )
{
*ptr = malloc(10);
}
And called like
test( &ptr_main );
Thus dereferencing the pointer ptr in the function we get a direct access to the pointed object (pointer) ptr_main and it is the pointed (referenced) object that is changed now in the function
To make it more clear consider the following demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f1( int *px )
{
*px = 10;
}
void f2( int **ppx )
{
*ppx = malloc( sizeof( int ) );
**ppx = 20;
}
int main(void)
{
int x = 0;
printf( "Before calling f1 x = %d\n", x );
f1( &x );
printf( "After calling f1 x = %d\n", x );
int *px = &x;
printf( "Before calling f2 px = %p and *px = %d\n", ( void * )px, *px );
f2( &px );
printf( "After calling f2 px = %p and *px = %d\n", ( void * )px, *px );
free( px );
return 0;
}
The program output might look like
Before calling f1 x = 0
After calling f1 x = 10
Before calling f2 px = 0x7ffe79dd572c and *px = 10
After calling f2 px = 0x55db88f5d270 and *px = 20
To change the object x declared in main in the function f1 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
The same situation takes place with the pointer px. Pointers are objects. If we want to change the pointer px declared in main in the function f2 we need to pass it to the function by reference. Otherwise the function will deal with a copy of the value of the object.
And as you can see from the program output the function f2 indeed changed the value of the pointer px declared in main.
I am learning some of the basics of C, and am currently stepping my way through arrays and more specifically how passing by reference works. When the below code is run it returns 10 22. When I read through the code however, based on the last command it seems as though the variable a should return 22 instead of 10 (meaning the full output would be 22 22 instead of 10 22). Why would the variable a not update to 22 in this code?
#include <stdio.h>
void set_array(int array[4]);
void set_int(int x);
int main(void)
{
int a = 10;
int b[4] = { 0, 1, 2, 3 };
set_int(a);
set_array(b);
printf("%d %d\n", a, b[0]);
}
void set_array(int array[4])
{
array[0] = 22;
}
void set_int(int x)
{
x = 22;
}
Arrays are [loosely] "pass by reference". Actually, the array "decays" into an int *.
But, scalars are "pass by value".
In set_int, you set the function scoped copy of x but do not return it to the caller.
Here's the refactored code, with a "call by reference" example:
#include <stdio.h>
void
set_array(int array[4])
{
array[0] = 22;
}
int
set_int(int x)
{
x = 22;
return x;
}
void
set_int_byptr(int *x)
{
*x = 37;
}
int
main(void)
{
int a = 10;
int b[4] = { 0, 1, 2, 3 };
int c = 4;
#if 0
set_int(a);
#else
a = set_int(a);
#endif
set_array(b);
set_int_byptr(&c);
printf("a=%d b=%d c=%d\n", a, b[0], c);
return 0;
}
In C if you want to modify variable passed to function you need to pass the pointer to it:
examples:
int setval(int *obj, int value)
{
*obj = val;
return val;
}
void usage()
{
int x;
setval(&x, 22);
}
void *setpointer(void **ptr, size_t size)
{
*ptr = malloc(size);
return *ptr;
}
void usage1()
{
int *array;
setpointer(&array, 200*sizeof(*array));
}
First we need to get this out of the way, because I honestly believe it will make things less confusing - C does not pass any function arguments by reference, ever. C passes all function arguments by value. Sometimes, those values are pointers. This is not the same thing as pass-by-reference.
Among other things, pass-by-value means that any changes to a formal parameter are not reflected in the actual parameter. In your set_int function, x is a distinct object from a, and any changes to x do not affect a.
If we want a function to modify the value in a parameter, we must pass a pointer to that parameter:
void set_int( int *x )
{
*x = 22; // writes a new value to the thing x points to
}
int main( void )
{
int a = 10;
set_int( &a ); // foo writes a new value to a
return 0;
}
In the above code, we want the function set_int to update the variable a, so we must pass a pointer to a to the function.
x == &a // int * == int *
*x == a // int == int
Thus, writing a new value to the expression *x in set_int is the same as writing a new value to a in main. Any change to x itself is local to set_int.
Things get confusing when we add arrays to the mix. An array is not a pointer; however, unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T" and the value of the expression will be the address of the first element.
When you call set_array(b), the expression b "decays" from type "4-element array of int" (int [4]) to type "pointer to int" (int *), and the value of the expression is the same as &b[0].
Here's another confusing thing - in a function parameter declaration, array declarations of type T a[N] and T a[] are interpreted as T *a - a is a pointer to T, not an array of T. So your prototype
void set_array(int b[4])
is interpreted as
void set_array(int *b)
and what it receives is a pointer to the first element. As a practical matter, this means that any changes to array[i] in set_array are reflected in b, but this is fallout from how C specifically treats array expressions, not a difference in parameter passing mechanisms. The argument is still being passed by value, it's just that the argument is a pointer value that's the result of a well-defined conversion operation on array expressions.
You are doing 2 things over here:
1) Pass by value:
the function set_int(), its parameter is passed simply, without any address, which means it is pass by value, and any change made by this function set_int() will not be reflected in the calling function.
2) Pass by reference:
However, in the case of set_array(b), you are passing the array to the called function, and its base address will be passed (Means address of first element of b, that is &b[0]), hence this is pass by reference and any change is made to this value will be reflected in the calling function
which is the reason 22 is updated for b, but 22 didn't get update for a