Well, i have this simple example that we must use in school but i dont understand why we must use pointers and what they exactly do in same cases.
int **create(int lines, int columns)
{
int **p, i;
p = (int **) malloc(lines * sizeof(int *));
for(i = 0; i < lines; i++)
p[i] = (int *) malloc(columns * sizeof(int));
return p;
}
I google that **
is pointer to pointer. Simply pointer pointing to pointer that has stored address of variable. But WHY I should do that? And then these two lines of code looks to have totally random pointers
p = (int **) malloc(lines * sizeof(int *));
p[i] = (int *) malloc(columns * sizeof(int));
Basically I understand that pointer is pointing to address of variable or something but don't know what is happening here. Please if can somebody explain it to me. Thanks for your time.
A pointer can also be understood as an array. You allocate some space with malloc
, and you can set items with the []
operator, just like as arrays.
int* arr = (int*)malloc(sizeof(int)*3);
arr[1] = 5;
printf("%d", arr[1]); //output is 5
Pointers to pointers can be understood as two-dimensional arrays: You allocate space for the pointers , then allocate each pointer as an array.
int** arr = (int**)malloc(sizeof(int*) * 3);
for (int i = 0; i < 3; i++) {
arr[i] = (int*)malloc(sizeof(int) * 3); // each element is going to be an array of 3 integers
}
arr[2][2] = 4;
printf("%d", arr[2][2]); // 4
This function creates a matrix which is a two dimensional array.
An array is a sequence of elements stored contiguously in memory. With malloc
we allocate a memory block that can be used as an array. We then hold a pointer to the block of elements. We can then use the notation a[i]
to identify the ith element of the array whose address is stored in a
.
The expression malloc(n * sizeof(int));
allocates a memory block with room for n
integers. Note that it returns a pointer to an integer : int *
.
When we create a two dimensional array, each row is an array allocated with the above instruction. n
is replaced by the number of columns.
All the rows are then bundled together with an array of arrays. Remember that an array is of type int *
. Thus an array of arrays has int *
values as element. It's type is then int **
.
The first malloc
in your code allocates the array that will hold all the rows array. This is why its type is int **
. Its byte size is lines
time the byte size of an int *
.
In the for
loop, each row is instantiated and assigned to the corresponding element of the array p
.
The pleasant thing of the returned two dimensional array is that you may then identify on of its elements by the expression a[i][j]
.
Note that there is a mistake in this code.
The for loop is for(i = 0; i < riadky; i++)
. riadky
is an undefined variable. It's not the right variable name.
Now that you hopefully understand the code, could you find the correct variable name to put there ? You should be able to find it from my explanations.
Some pictures should help.
We start with the object p
:
int **
+–––+
p: | |
+–––+
p
has type int **
, meaning it can store the address of an object of type int *
.
For simplicity's sake, we'll assume both lines
and columns
are 2
. So we start by dynamically allocating enough space for two objects of type int *
, and store the address of the first of those objects into p
:
int ** int *
+–––+ +–––+
p: | | ––––––> | |
+–––+ +–––+
| |
+–––+
The array subscript operation a[i]
is defined as *(a + i)
- given a starting address a
, offset i
elements ( not bytes ) from that address 1 and dereference the result 2 . So the expression p[0]
refers to the first element and p[1]
the second:
int ** int *
+–––+ +–––+
p: | | ––––––> | | p[0]
+–––+ +–––+
| | p[1]
+–––+
Now, for each p[i]
, we allocate enough space for 2 int
objects and assign the address of the first of each set into p[i]
:
int ** int * int
+–––+ +–––+ +–––+
p: | | ––––––> | | p[0]-––> | | p[0][0]
+–––+ +–––+ +–––+
| | p[1]–+ | | p[0][1]
+–––+ | +–––+
|
| +–––+
+-> | | p[1][0]
+–––+
| | p[1][1]
+–––+
As for why you need to use multiple levels of indirection ( **
, ***
, etc.)...
For any object E
of type T
, the expression &E
evaluates to the address of that object, and the type of that expression is T *
(pointer to T
). If we repace T
with a pointer type P *
, then the type of &E
is P **
. IOW, the type of an object that holds the address of another object must have one more level of indirection than the pointed-to object.
p
has type int *
and points to an int
object, then p+1
points to the next int
object immediately following, whether that object is 2, 4, or more bytes away.a
an address?” Except when 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.