How are the pointed-to values of pointers being printed? - c

I found the following code in my textbook:
#include<stdio.h>
void disp( int *k)
{
printf("%d",*k);
}
int main( )
{
int i ;
int marks[ ] = { 55, 65, 75, 56, 78, 78, 90 } ;
for ( i = 0 ; i <= 6 ; i++ )
disp ( &marks[i] ) ;
return 0;
}
}
The code works just fine, but I have doubts regarding the logic:
I am sending the address of variables of the array. But in the disp function I am using a pointer variable as the argument and printing the value of the pointer. So the type of argument sent from the main function should mismatch with the argument of disp. So how does it work?
I tried to do the same by changing the disp function as
void disp( int (&k))
{
printf("%d",*k);
}
but I am getting an error. What should I do to make it work by taking an address as an argument, i.e. void disp(int &k)?

1) I am sending the address of variables of the array. But in the disp function I am using a pointer variable as argument and printing the value of the pointer.
Understand that a pointer is an address. So &marks[i] is an int*. And you're not printing the value of the pointer, but the value it points to.
printf("%d",*k);
the *k dereferences the pointer and gives the pointed-to value.
void disp( int (&k))
is invalid syntax in C, &k is not a valid identifier.

When you do: -
int *k = &marks[i];
The above statement is broken into: -
int *k; -> Integer Pointer
k = &marks[i]; --> `k` points to the address of marks[i]
So, basically, k is the an integer pointer, that points to the address of the current element in your array.
So, when you print *k, it is equivalent to: - *(&marks[i]), which dereferences the value and prints the element marks[i].
So, in the below code, you can understand, how the whole process of pointer assignment and de-referencing takes place: -
int *k; // Declaring integer pointer.
// Actually 'k' is equal to the `&marks[i]`.
// '*k' is just the indication of it being a pointer
k = &marks[i];
// Dereference pointer
*k = *(&marks[i]); --> = marks[i]
printf("%d",*k); --> printf("%d",marks[i]);
Also, since you cannot declare variable like: -
int &k = &marks[i];
You cannot have them as parameter in your function: -
void disp(int &k);
Because, eventually the address of array element passed is stored in this variable. So, it has to be int *k.

1) You understand correct that in the for loop the address is sent to disp. But disp receives pointer as an argument... which is just an address. Inside that function you don't print the "value" of the pointer. You print the value pointed by that pointer (the value that is on that address). In the printf call "*k" you dereference the pointer - get the value pointed by that pointer.
2) You didn't change the function so that it receives address. You changed it so that it receives reference. You can also say it receives a hidden pointer - it does the same as the pointer but you don't need to "*k" to dereference it - you use it as a normal variable

Read up on pointers and address-of variable. And how they're used.
When a function expects a pointer, you HAVE to send either a pointer or an address of a variable. Since pointers hold addresses.
The second problem you're facing is that of syntax error. Because there is no & operator that can be applied to "lvalues".

Well, simply i can say that you are passing an address in the function and recieving it in a pointer..Its correct as pointer can point to or hold the address. Or other way simply if you send an address but store it in a reference variable but the reference of whom, is the question to be asked. Try vice versa you'll understand the structure more better...

Related

Double pointers as arguments in C

I am having some problems with double pointers as arguments in C.
From what I know so far:
when I have a function that takes a pointer as an argument, say a function called functionX(int *y)
then when I call functionX, let's say by: functionX(&randomvar),where randomvar is an integer containing a certain value (let's say 5), then C will create a pointer that is also called 'randomvar' that contains the address of randomvar. So the output of *randomvar will be 5.
Is my understanding correct?
If so, then when the function has double pointers : functionX(int **y) and by doing functionX(&randomvar) creates 2 pointers, one that contains the address of randomvar, another that contains the address of the first pointer.
I'm a bit stumped here I'm not sure if it's correct.
From what I know so far: when I have a function that takes a pointer
as argument, says a function called functionX(int *y) then when I
call functionX, let's say by: functionX(&randomvar),where
randomvar is an integer containing a certain value (let's say 5),
then C will create a pointer that is also called 'randomvar' that
contains the addresse of randomvar. So the ouput of *randomvar
will be 5.
Is my understanding correct?
No.
The situation you describe would be along these lines:
void functionX(int *y) {
// ...
}
int main(void) {
int randomvar = 5;
functionX(&randomvar);
}
The expression &randomvar in the main() function of that code does evaluate to the address of that function's local variable randomvar. The expression has type int *, the same as parameter y to function functionX(), so it is well suited for use as an argument to that function. All well and good so far.
But the expression &randomvar designates only a value, not an object. There is no storage reserved for it, and therefore it does not have an address. It also has no name, and in particular, it is not named 'randomvar'. Inside function functionX(), (a copy of) that value can be accessed as y, and the expression *y will evaluate to 5. Nowhere in the code presented is *randomvar a semantically valid expression.
If so
It is not so.
, then when the function has double pointers : functionX(int **y) and by doing functionX(&randomvar) creates 2 pointers, one that contains the adresse of randomvar, another that contains the adresse of the first pointer.
Not at all. &randomvar is a single expression. Evaluating it produces one value, which, as I've already covered, has type int *. This is does not match a function parameter of type int **. An int ** is a pointer to an int *. To obtain one, you might take the address of an object (not a value) of type int *:
void functionY(int **z) {
// ...
}
int main(void) {
int randomvar = 5;
int *varptr = &randomvar;
functionY(&varptr);
}
When done that way, there are indeed two pointers, one an int * and the other an int **, but the former needs to be declared explicitly.
Visualize it this way:
void foo(int a);
void bar(int *b);
void baz(int **c);
// main function
{
int x = 5;
int *p = &x;
foo(x);
bar(p);
baz(&p);
}
// **main** mem space
virtual mem address var name (conceptual) value
=================== ===================== =====
ABCD:4000 x 5
ABCD:4008 p ABCD:4000
// **foo** mem space
virtual mem address var name (conceptual) value
=================== ===================== =====
BCDE:2000 a 5
// a new variable is created.
// any changes made on 'a' will not affect 'x' in 'main'
// **bar** mem space
virtual mem address var name (conceptual) value
=================== ===================== =====
BCDE:4000 b ABCD:4000
// a new pointer is created pointing to 'x'
// 'b' points to 'x' and '*b' means 'the value stored in ABCD:4000'
// any changes made on '*b' will affect 'x' in main
// **baz** mem space
virtual mem address var name (conceptual) value
=================== ===================== =====
BCDE:8000 c ABCD:4008
// a new pointer is created pointing to 'p'
// 'c' points to 'p' and '*c' means 'the value stored in ABCD:4008'
// any changes made on '*c' will change the value of 'p' in main
// if '**c = 7' is executed, x will be assigned '7'
// if '*c = ABCD:8000' is executed, p will no longer point to 'x'
hen when I call functionX, let's say by: functionX(&randomvar),where
randomvar is an integer containing a certain value (let's say 5), then
C will create a pointer that is also called 'randomvar' that contains
the addresse of randomvar
The name of the pointer in the function functionX is y because you wrote yourself that it is the name of the function parameter functionX(int *y).
If so, then when the function has double pointers : functionX(int **y)
and by doing functionX(&randomvar) creates 2 pointers, one that
contains the adresse of randomvar, another that contains the adresse
of the first pointer. If you have a function declared for example like
The operator & creates one pointer not two pointers.
If you have a function declared for example like
void functionX(int **y);
and a variable declared like
int randomvar = 5;
then such a call of the function like
functionX( &randomvar );
generates a compilation error because the type of the argument is int * while the type of the parameter according to the function declaration is int **.
You may not write for example like
functionX( &&randomvar );
because using the first operator & creates a temporary object of the type int *. And you may not apply the operator & to a temporary object.
To call the function you could write
int *p = &randomvar;
functionX( &p );
In this case the type of the argument will be int ** as it is required by the parameter type.
Here is a demonstrative program.
#include <stdio.h>
void f( int *p )
{
printf( "The value of p is %p\n"
"the pointed value is %d\n",
( void * )p, *p );
}
void g( int **p )
{
printf( "The value of p is %p\n"
"the pointed value is also a pointer %p\n"
"the pointed value by the dereferenced pointer is %d\n",
( void * )p, ( void * )*p, **p );
}
int main(void)
{
int x = 5;
f( &x );
putchar( '\n' );
int *p = &x;
g( &p );
return 0;
}
Its output might look for example like
The value of p is 0x7ffced55005c
the pointed value is 5
The value of p is 0x7ffced550060
the pointed value is also a pointer 0x7ffced55005c
the pointed value by the dereferenced pointer is 5
You can just keep chaining pointers forever if you like. Here's some code that demonstrates this:
#include<stdio.h>
void foo(int ***A, int **B, int *C) {
printf(" %p A\n %p *A\n %p **A\n %d ***A\n", A, *A, **A, ***A);
printf(" %p B\n %p *B\n %d **B\n", B, *B, **B);
printf(" %p C\n %d *C\n ", C, *C);
}
int main(void) {
int D = 8;
int* C = &D;
int** B = &C;
int*** A = &B;
foo (A,B,C);
printf("%p &D (in main)\n", &D);
return 0;
This will give results like this for the dereferenced pointers, each '*' comes off just as it goes on, so notice how **A = *B = C = &D
0x7ffc81b06210 A
0x7ffc81b06218 *A
0x7ffc81b06224 **A
8 ***A
0x7ffc81b06218 B
0x7ffc81b06224 *B
8 **B
0x7ffc81b06224 C
8 *C
0x7ffc81b06224 &D (in main)
Note finally that the call foo (&B, &C, &D) will produce the same result.
There is no pointer made of the same name as the passed variable when invoking a function with an address of a passed variable as argument. It simply passes the address of a certain variable when preceded by the & operator. Inside the called function the pointer which holds this address can have any valid identifier.
when the function has double pointers : functionX(int **y) and by doing functionX(&randomvar) creates 2 pointers, one that contains the adresse of randomvar, another that contains the adresse of the first pointer.
You cannot pass the address of an int object, which is of type int*, when the function expects an object of type int**.
Speaking for passing double pointers in general, the concept is the same as said above.
No, your understanding is not correct. C doesn't "create" anything in the sense you assumed -- most variables are simply labels of memory locations (not only though, they may "alias", or label, CPU registers) -- your randomvar in the scope where functionX is called is a label of a memory area allocated to store an integer and which is interpreted as integer. The value of &randomvar unary expression (operator & with a single operand randomvar) is the address of the data. That address is what is passed to functionX as y, meaning that a memory location (or CPU register) is reserved and stores the address (not the value) of randomvar.
As an example, say your program declares a variable like int randomvar; -- when executed, a part of RAM -- 4 bytes for an int typically -- is reserved to hold the variable value of randomvar. The address isn't known until the program is executing in memory, but for the sake of the example let's imagine the address 0xCAFEBABEDEADBEEF (8 bytes) is the one that points to the 4 bytes to hold the integer value. Before the variable is assigned a value, the value at the address is indeterminate -- a declaration of a variable only reserves the space to hold the value, it doesn't write anything at the address, so before you assign a value to the variable, you shouldn't even be using the value at all (and most C compilers can warn you about this).
Now, when the address is passed to functionX this means that for the function, label y is 8 bytes reserved at some memory location, to store an address of an integer variable. When called like functionX(&randomvar), y stores 0xCAFEBABEDEADBEEF. However, y also [typically] has an address -- the former value (address of randomvar) has to be stored somewhere! Unless a CPU register stores the value, in which case there is no [RAM] address, naturally.
For a pointer to a pointer like int * * y, y labels a memory location reserved to store an address to an address of an integer variable.

What is the difference between pointer to array and pointer to pointer?

I'm new in programming and learning about pointers in array. I'm a bit confused right now. Have a look at the program below:
#include <stdio.h>
int fun();
int main()
{
int num[3][3]={23,32,478,55,0,56,25,13, 80};
printf("%d\n",*(*(num+0)+1));
fun(num);
printf("%d\n", *(*(num+0)+1));
*(*(num+0)+0)=23;
printf("%d\n",*(*(num+0)));
return 0;
}
int fun(*p) // Compilation error
{
*(p+0)=0;
return 0;
}
This was the program written in my teacher's notes. Here in the main() function, in the printf() function dereference operator is being used two times because num is pointer to array so first time dereference operator will give pointer to int and then second one will give the value at which the pointer is pointing to.
My question is that when I'm passing the array name as argument to the function fun() then why *p is used; why not **p as num is a pointer to array?
Second thing why *(p+0) is used to change the value of zeroth element of the array; why not *(*(p+0)+0)=0 as in the main() function *(*(num+0)+0) is used to change the value of zeroth element?
The whole thing is very confusing for me but I have to understand it anyway. I have searched about this and found that there is a difference between pointer to array and pointer to pointer but I couldn't understand much.
The trick is the array-pointer-decay: When you mention the name of an array, it will decay into a pointer to its first element in almost all contexts. That is num is simply an array of three arrays of three integers (type = int [3][3]).
Lets analyse the expression *(*(num + 1) + 2).
When you mention num in the expression *(num + 1), it decays into a pointer to its first element which is an array of three integers (type = int (*)[3]). On this pointer pointer arithmetic is performed, and the size of whatever the pointer points to is added to the value of the pointer. In this case it is the size of an array of three integers (that's 12 bytes on many machines). After dereferencing the pointer, you are left with a type of int [3].
However, this dereferencing only concerns the type, because right after the dereferencing operation, we see expression *(/*expression of type int[3]*/ + 2), so the inner expression decays back into a pointer to the first array element. This pointer contains the same address as the pointer that results from num + 1, but it has a different type: int*. Consequently, the pointer arithmetic on this pointer advances the pointer by two integers (8 bytes). So the expression *(*(num + 1) + 2) yields the integer element at an offset of 12 + 8 = 20 bytes, which is the sixth integer in the array.
Regarding your question about the call of fun(), that call is actually broken, and only works because your teacher did not include the arguments in the forward declaration of fun(). The code
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
fun(num);
}
would have generated a compile time error due to the wrong pointer type. The code of your teacher "works", because the pointer to the first array in num is the same as the pointer to the first element of the first array in num, i. e. his code is equivalent to
int fun(int* arg);
int main() {
int num[3][3] = ...;
...
//both calls are equivalent
fun(num[0]);
fun(&num[0][0]);
}
which would compile without error.
This example shows a matrix, pointers to the first integers of arrays, and pointer to pointer
#include<stdio.h>
int fun(int (*p)[3]); /* p is pointer to array of 3 ints */
int main()
{
/* matrix */
int num[3][3]={{23,32,478},{55,0,56},{25,13, 80}};
/* three pointers to first integer of array */
int *pnum[3] = {num[0], num[1], num[2]};
/* pointer to pointer */
int **ppnum = pnum;
printf("%d\n", *(*(num+1)+2));
fun(num);
printf("%d\n", *(*(num+1)+2));
pnum[1][2] = 2;
printf("%d\n", *(*(num+1)+2));
ppnum[1][2] = 3;
printf("%d\n", *(*(num+1)+2));
return 0;
}
int fun(int (*p)[3])
{
p[1][2]=1;
return 0;
}
You do not actually need any pointers to print anything here.
Your int num[3][3] is actually an array of three elements, each of which is an array of three integers. Thus num[0][0] = 23, num[1][1] = 0, and so on. Thus you can say printf("%d", num[0][0]) to print the first element of the array.
Pointer to variable:
Pointer is variable which stores the address( of a variable). Every one know that.
Pointer to Array:
An array is a variable which has the starting point(address) of group of same objects.
And the pointer is a variable which stores the starting point(address) of an Array.
For example:
int iArray[3];
iArray is a variable which has an address value of three integers and the memory is allocated statically. And the below syntax is provided in a typical programming languages.
// iArray[0] = *(iArray+0);
// iArray[1] = *(iArray+1);
// iArray[2] = *(iArray+2);
In the above the iArray is a variable through which we can access the three integer variables, using any of the syntax mentioned above.
*(iArray+0); // Here iArray+0 is the address of the first object. and * is to dereference
*(iArray+1); // Here iArray+1 is the address of the second object. and * is to dereference
So simple, what is there to confuse.
The below lines are for your understanding
int iArray1[3];
int iArray2[3][3];
int *ipArray = 0;
ipArray = iArray1; // correct
ipArray = iArray2[0]; // correct
ipArray = iArray2[2]; // correct
int **ippArray = iArray2; // wrong
As per the above last line, compiler will not take it as a valid assignment. So **p is not used.
Pointer arthmatic cannot be applied on double arrays because of the way memory is allocated.

How does the compiler understand whether the given function does a pass by value or pass by referene?

How does the C compiler understand whether the given function does a pass by value or pass by reference?
what will happen if the pointer of a variable is passed as integer (as pass by value) to a function ? OR is this possible in C ?
ie: the address of a variable is copied to another variable(int) and that variable is passed to a function. here the called function will get an address as normal integer parameter. Is this possible in C? if not why?
In C it is possible only the pass by value (by reference is supported only in C++).
Both a standard variable and a pointer variable are passed by value. So, the compiler must not make any check about reference or value.
standard variables and pointer variables are same, both store values, but a pointer variable can store only an address value and supports the dereferencing operator '*', this operator get the value pointed by the pointer variable.
Thanks to this, when you pass by value (C support only by value) a pointer variable, the value of the pointer variable is copied in a local pointer variable (instanced in the function stack) this variable is the pointer argument of the function. So you can access to address value copied in the local pointer variable using the dereferencing operator.
Added comments 08/22/14
I can better explain with a example:
void FuncSet10(int* PtrArgument)
{
// The PtrArgument is a local pointer variable
// it is allocated in the stack. The compiler
// copies the MyIntVariable address in this variable
// Using dereferencing operator I can access to
// memory location pointed by PtrArgument
*PtrArgument = 10;
}
void FuncSet20(int IntArgument)
{
// The IntArgument is a local variable
// allocated in the stack. The compiler
// copies the MyIntVariable address in this variable
// this code emulates the dereferencing operator
// and so poiter mechanism.
*((int*)IntArgument) = 20;
}
void FuncMovePointer(int* pointer)
{
int a = *pointer++; // now a contains 1
int b = *pointer++; // now b contains 2
int c = *pointer++; // now c contains 3
printf("a contains %d\n", a);
printf("b contains %d\n", b);
printf("c contains %d\n", c);
// The *Ptr now points to fourth (value 4) element of the Array
printf("pointer points to %d\n", *pointer);
}
int _tmain(int argc, _TCHAR* argv[])
{
int Array[] = {1, 2, 3, 4}; // Array definition
int* pointer = Array; // pointer points to the array
int MyIntVariable;
// First example for explanation of
// the pointer mechanism and compiler actions
// After calling this function MyIntVariable contains 10
FuncSet10(&MyIntVariable);
printf("MyIntVariable contains %d\n", MyIntVariable);
// After calling this function MyIntVariable contains 20
// This code emulate pointer mechanism
FuncSet20((int)&MyIntVariable);
printf("MyIntVariable contains %d\n", MyIntVariable);
// Second example to demonstrate that a pointer
// is only a local copy in a called function
// Inside function the pointer is incremented with ++ operator
// so it will point the next element before returning by function
// (it should be 4)
FuncMovePointer(pointer);
// But this is not true, it points always first element! Why?
// Because the FuncMovePointer manages a its local copy!
printf("but externally the FuncMovePointer it still points to first element %d\n", *pointer);
return 0;
}
I hope that above code can help better your understanding.
Angelo
How does the C compiler understand whether the given function does a
pass by value or pass by reference?
For your information C not understand about pass by reference. You can send pointer to variable.
what will happen if the pointer of a variable is passed as integer (as
pass by value) to a function ?
Passing the pointers to a variable and the accessing it using dereferencing within the function.So By passing a pointer to a function you can allow that function to read and write to the data stored in that variable.
For example
void myfunc( int *myval ) // pointer "myval" point address of "locvar"
{
*myval = 77; //place value 77 at address pointed by "myval"
}
int main()
{
int locvar=10; //place value 10 at some address of "locvar"
printf("locvar = %d\n",locvar);
myfunc(&locvar); // Here address of "locvar" passed
printf("locvar = %d\n",locvar);
return 0;
}

Passing address, but it is working like call by value in C?

Hello I am a beginner in C programming language. Recently I read about call by value and call by address. I have learned that in call by address changes in the called functions reflects the callee. However the following code does not work like that.
int x = 10,y = 20;
void change_by_add(int *ptr) {
ptr = &y;
printf("\n Inside change_by_add\t %d",*ptr);
// here *ptr is printing 20
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d", *p);
// here *p is still pointing to address of x and printing 10
}
When I am passing address then why the changes made by called function does not reflect caller?
The function is assigning a new address to the pointer but the pointer itself is being passed by value, as all arguments are in C. To change the value of a pointer variable the address of the pointer itself must be passed:
void change_by_add(int **ptr)
{
*ptr = &y;
}
change_by_add(&p);
See C FAQ Question 4.8.
Passing by reference does not exist in C but can be achieved by passing the address of the variable who's value is to be changed to a function. For example:
void add_to_int(int* a_value, int a_increment)
{
*a_value += a_increment;
}
You are simply setting the value of the pointer in the function, not the value of the pointed to variable. The function should use the following code:
*ptr = y;
This derefences the pointer (exposing the value pointed to), and therefore when you use the equals operator, the memory pointed at is modified, not the pointer itself. I hope this helps to clarify things.
Changes made by called function does not get reflected by the caller because you are overriding the pointer address in the called function i.e ptr = &y;.
Initially, you passed the address of x but you are changing it with the address of y.
If you really want to implement the concept of call by address then change value instead of address.
Example:
void change_by_add(int *ptr) {
*ptr = y; //changing value
printf("\nInside change_by_add\t %d",*ptr);
}
void main(){
int *p;
p = &x;
change_by_add(p);
printf("\nInside main\t %d \n", *p);
return 0;
}
Output
Inside change_by_add 20
Inside main 20
There is no such thing as call by address in C. There is only call by value. What one does when a function needs to modify an argument in a way that is visible to the caller is to have the caller pass a pointer to something, and have the called function write the update though that pointer. Note that the pointer itself is still sent as call-by-value - that is: the called function gets its own copy of the pointer and could change it to point to anything else if it wants to.

Double pointers are also sometimes employed to pass pointers to functions by reference

" Double pointers are also sometimes employed to pass pointers to functions by reference "
can somebody can explain me the above statement, what exactly does point to function by reference means ?
I believe this example makes it clearer :
//Double pointer is taken as argument
void allocate(int** p, int n)
{
//Change the value of *p, this modification is available outside the function
*p = (int*)malloc(sizeof(int) * n);
}
int main()
{
int* p = NULL;
//Pass the address of the pointer
allocate(&p,1);
//The pointer has been modified to point to proper memory location
//Hence this statement will work
*p=10;
//Free the memory allocated
free(p);
return 0;
}
It means that you have a function that takes a pointer pointer (type int ** for example). This allows you to modify the pointer (what data it is pointing to) much in the way passing a pointer by reference would allow.
void change (int *p) {*p = 7;}
void Really_Change (int **pp) {*pp = null;}
int p = 1;
int *pp = &p;
// now, pp is pointing to p. Let's say it has address 0x10;
// this makes a copy of the address of p. The value of &p is still 0x10 (points to p).
// but, it uses that address to change p to 7.
change(&p);
printf("%d\n", p); // prints 7;
// this call gets the address of pp. It can change pp's value
// much like p was changed above.
Really_Change(&pp);
// pp has been set to null, much like p was set to 7.
printf("%d\n", *pp); // error dereference null. Ka-BOOM!!!
So, in the same way that you can pass a pointer to an int and change the value, you can pass a pointer to a pointer and change its value (which changes what it points to.)
I'll try to explain with both code and plain english :). The explanation may get long, but it will be worth the while.
Suppose we have a program, running its main() function, and we make a call to another function that takes an int parameter.
Conceptually, When you pass a variable as a parameter to a function, you can do so in (roughly speaking) two ways: by value, or by reference.
"By value" means giving the function a copy of your variable. The function will receive its "content" (value), but it won't be able to change the actual variable outside its own body of code, because it was only given a copy.
"By reference", on the other hand, means giving the function the actual memory address of our variable. Using that, the function can find out the variable's value, but it can also go to that specified address and modify the variable's content.
In our C program, "by value" means passing a copy of the int (just taking int as argument), and "by reference" means passing a pointer to it.
Let's see a small code example:
void foo(int n) {
n = 10;
printf("%d\n", n);
}
int main() {
int n = 5;
foo(n);
printf("%d\n", n);
return 0;
}
What will the output of this program be? 10 10? Nope. 10 5! Because we passed a copy of the int, by value and not by reference, foo() only modified the number stored in its copy, unable to reach main()'s copy.
Now, if we do it this way:
void foo(int* n) {
*n = 10;
printf("%d\n", *n);
}
int main() {
int n = 5;
foo(&n);
printf("%d\n", n);
return 0;
}
This time we gave foo() our integer by reference: it's actual memory address. foo() has full power to modify it by accessing it's position in memory, foo() and main() are working with the same copy, and so the output will be 10 10.
As you see, a pointer is a referece,... but also a numerical position in memory. It's similar to an int, only the number contained inside is interpreted differently. Think of it this way: when we pass our int by reference, we're passing an int pointer by value!. So the same by value/by reference logic can be applied to pointers, even though they already are references.
If our actual variable was not an int, but an int reference (pointer), and we wanted main() and foo() to share the same copy of that reference so that foo() can modifiy it, what would we do? Why of course, we'd need a reference to our reference! A pointer to a pointer. That is:
int n; /* integer */
int* n; /* integer reference(pointer). Stores an int's position in memory */
int** n; /* reference to integer reference, or double pointer.
Stores int*'s memory address so we can pass int*s by reference. */
I hope this was useful.

Resources