#include <stdio.h>
#include <stdlib.h>
void input(int **ar, int *n) {
printf("Number of elements: ");
scanf("%d", n);
*ar = (int*)malloc(*n * sizeof(int));
//*ar = new int[*n];
for (int i = 0; i < *n; i){
printf("Element %d:", i);
scanf("%d", &(*ar)[i]);
}
return;
}
void output(int *ar, int n) {
for (int i = 0; i < n; i) {
printf("]\n", ar[i]);
}
return;
}
int main() {
int n = 0;
int *ar = NULL;
input(&ar, &n);
output(ar, n);
free(ar);
return 0;
}
So I have just learned about pointers in C at my university. Some of it I understand and some I don't. For example, I don't understand why ar
in the input
function is an int**
and not an int*
. I mean I try to replace int** ar
with int* ar
and delete the *
in int* ar = NULL
in the main
function and there's no compile error. When I run the program, everything works fine. I enter the number of elements and enter some values in those elements but, when I enter the last number in the last element, I get nothing. So I undid everything and the program works normally again.
CodePudding user response:
A common use of pointers, as they're being used here, is to allow a function call to change the value of one of your variables.
For example, suppose you had the following:
void
change_num(int num)
{
num = 6;
}
int
main()
{
int num = 5;
change_num(num);
printf("%i\n", num);
return 0;
}
This doesn't work because change_num
is changing its own copy of num
and not num
itself.
Instead, you have to pass a pointer to num
to the function:
void
change_num(int* num_ptr)
{
*num_ptr = 6;
}
int
main()
{
int num = 5;
change_num(&num);
printf("%i\n", num);
return 0;
}
The line *num_ptr = 6;
means, "Change the object pointed to by num_ptr
to 6."
In the general case, if we want a function to change the value of a variable of type SomeType
, then we must pass a SomeType*
to the function.
In your case, you want to change the value of ar
, which is an int*
. Right now, it doesn't hold the address of anything (NULL
) and you want it to be changed to hold the value of an allocated array (created by malloc
). If we pass an int*
to a function in order to change an int
and we pass a SomeType*
in order to change a SomeType
, then we must pass an int**
in order to change an int*
.
CodePudding user response:
The program you have posted is doing following (in the given sequence below):
- Declare/define a pointer in a function
- Allocate memory to that pointer in some other function and fill that memory with user input
- Print the content of that memory using another function
- Deallocate memory and exit
The part which is confusing you is 2.
I don't understand why ar in the input function is an int** and not an int* ....
If you want to allocate memory to a pointer (or want to change the pointer, like, e.g. making it point to some other memory or reallocating memory etc.) in some other function, you need access of that pointer in that function and you can get access if you have the address of that pointer.
And that's why here the address of ar
pointer is passed:
input(&ar, &n);
Pass address of ar
to input()
function and in the input function dereference that address (i.e. *ar
) will give the ar
pointer (declared/defined in main()
).
For better understanding, I am renaming the ar
parameter of input()
function to input_ar
:
void input(int *input_ar, int *n) {
.....
.....
When input()
function called from main()
function, the in-memory view would be something like this:
input_ar ar
----- -----
| 200 | ----> | NULL|
----- -----
[200 is address of ar pointer]
In input()
function, when you do:
*input_ar = (int*)malloc(*n * sizeof(int));
dereferencing input_ar
(i.e. *input_ar
) will give ar
:
input_ar *input_ar (ar) (newly allocated memory block)
----- ----- -----
| 200 | ---------> | 300 | ----> | |
----- ----- -----
[300 is address of the newly allocated memory block]
Hence, by dereferncing input_ar
, the pointer ar
can be changed in input()
.
I mean I try to replace int** ar with int* ar and delete the * in int* ar = NULL in the main function and there's no compile error.
Note that if you remove the *
from declaration of ar
in main()
then ar
will be a variable of type int
, that means, it will not be a pointer but a variable which can hold a int
type value. If you do this change in your program, you have make changes in other places as well like that way you are taking input from user in input()
function, respective changes in output()
function etc.
You have not shown the program with the changes that you have done after deleting *
from ar
declaration so, I will just talk about the ar
argument passed to input()
:
This is what you might have tried:
int ar;
input (&ar, &n);
and in input()
:
void input(int *ar, int *n) {
printf("Number of elements: ");
scanf("%d", n);
ar = (int*)malloc(*n * sizeof(int));
.....
Note that the ar
pointer parameter is a local variable of input()
function.
When input()
function is called from main()
function, the ar
will hold the address of ar
variable of main()
function.
If you want, you can make changes in the value of ar
variable using the pointer ar
in input()
function, e.g. - *ar = 9;
This will assign value 9
to variable ar
(of main()
). The in-memory view would be something like this
ar (of input()) ar (of main())
----- -----
| 200 | -------------> | |
----- -----
[200 is address of ar variable of main()]
But when you do
ar = (int*)malloc(*n * sizeof(int));
the ar
has lost the address of ar
variable of main()
function and newly allocted memory reference is assigned to pointer ar
of input()
, i.e.
ar (of input()) newly allocated memory block
----- -----
| 400 | -------------> | |
----- -----
[400 is address of the newly allocated memory block]
You can write/modify the contents in this memory but when returned from input()
, this memory reference will be lost because input()
is not returning anything and this will be a memory leak in your program.