I've been reading a lot of the posts about allocating memory, and I think that I understand the concept, but I have been told that I have to use an approach that looks something like this:
double ** malloc_array2d(size_t m, size_t n)
{
double **A;
size_t i;
A = malloc(m * sizeof(double *));
if (A == NULL)
return NULL;
A[0] = (double *) malloc(m * n * sizeof(double));
if (A[0] == NULL)
{
free(A);
return NULL;
}
for (i = 1 ; i < m ; i++)
A[i] = A[0] + i *n;
return A;
}
And then of course I will have to free the memory later - but I just don't quite understand this kind of approach and more specifically I can't really see what happens in the last line where the remaining pointers are set into the block of memory (have i been told. And I am not sure how I will insert elements in the matrix/array when I am done allocating.
double ** malloc_array2d(size_t m, size_t n){
double **A;
size_t i;
A = malloc(m*sizeof(double *));
if (A == NULL) return NULL;
A[0]=(double *)malloc(m*n*sizeof(double));
if ( A[0] == NULL) {free(A); return NULL;}
for(i=1; i<m; i++) A[i]=A[0]+i*n;
return A;
}
Let's go Line by line:
A = malloc(m*sizeof(double *));
This line allocates space for m double pointers.
A[0] = (double *) malloc(m*n*sizeof(double));
A[0] is now a block of memory for m*n doubles, which is all the doubles we need for the 2d array.
for (int i = 1; i < m; i++) {A[i] = A[0] + i * n;}
because each A[i] is a block of n doubles, we want A[i] to start i*n doubles away from A[0].
Because all of this is in a solid block of memory, we can do some interesting things. For example, A[0][n] is the exact same double as A[1][0].
Furthermore, because everything is in one big block of memory, to access A[i][j] for any i < m, j < n, we just have to access the double at A[0] + i*j + j. This is much faster than going to A[i] which points to a double* B, and finding B[j].
Memory management is a difficult topic to understand and it takes some time. Hopefully this makes a bit more sense, and I hope I didn't confuse you even more :)
With this form of allocation, you start by allocating an array of pointers to other arrays, like so:
T **a = malloc( sizeof *a * N ); // N is the number of rows
sizeof *a is equivalent to sizeof (T *); each element of the array is going to be a pointer to T. When we're done, we have something like the following in memory:
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[N-1]
+---+
Now, for each of those elements, we allocate another chunk of memory to hold each element of type T:
a[i] = malloc( sizeof *a[i] * M ); // M is the number of columns
Each a[i] has type T *, so sizeof *a[i] is equivalent to sizeof (T).
After that's done, we have something that looks like this in memory:
+---+ +---------+---------+ +-----------+
a: | | a[0] ---> | a[0][0] | a[0][1] |...| a[0][M-1] |
+---+ +---------+---------+ +-----------+
| | a[1] ---> | a[1][0] | a[1][1] |...| a[1][M-1] |
+---+ +---------+---------+ +-----------+
| | a[2] ---> | a[2][0] | a[2][1] |...| a[2][M-1] |
+---+ +---------+---------+ +-----------+
...
+---+ +-----------+-----------+ +-------------+
| | a[N-1]--> | a[N-1][0] | a[N-1][1] |...| a[N-1][M-1] |
+---+ +-----------+-----------+ +-------------+
So basically what you've done here is allocate N separate M-element arrays of T, and then you collect the pointers to those arrays in an N-element array of T *.
You can access each element as a[i][j], like any normal 2D array; remember that the expression a[i] is defined as *(a + i); we offset i elements (not bytes!) from the address in a and then dereference the result. So a[i][j] is evaluated as *(*(a + i) + j ).
So, several things to remember with this form of allocation:
The "rows" of the array are not going to be contiguous in memory; the object in memory following a[i][M-1] is (most likely) not going to be a[i+1][0].
Since each "row" a[i] was allocated with a call to malloc, it must also be explicitly deallocated with a corresponding call to free before you deallocate a (always free in the reverse order that you malloc).
Even though we can treat a as a 2D-array, it does not have an array type, so you can't determine the size of the array using the sizeof a trick; you'll only get the size of the pointer type, not the total size of the array. So you'll want to keep track of the array size yourself.
You have to make each pointer of the pointer of poitners to point to valid malloc()ed data.
for (int i = 0 ; i < n ; ++i)
A[i] = (double *) malloc(m * sizeof(double));
You could also allocate it all at once, but then the notation A[i][j] will not work.
Related
So I know that the * operator is used for multiplication and as a pointer but sometimes I see the * operator and I am not sure what it means. Have a look at this code which defines a matrix
#ifndef MATRIX_H
#define MATRIX_H
/* The data structure representing a matrix */
typedef struct {
int rows; /* number of rows */
int columns; /* nuumber of columns */
int **content; /* matrix elements in a two dimensional array */
} matrix_t;
what does a double asterisk used for here?
I assume ** operator is used for pointers in 2d arrays but I am not sure.
Multiple indirection is a thing - you can have pointers to pointers, pointers to pointers to pointers, pointers to arrays of pointers, arrays of pointers to pointers, pointers to arrays of pointers to pointers to arrays of pointers to functions returning pointers, etc.
As used here, the intent is that you allocate an array of pointers:
matrix_t mat;
mat.content = calloc( 2, sizeof *mat.content );
which gives us
int ** int *
+---+ +---+
mat.content: | | ---> | | mat.content[0]
+---+ +---+
| | mat.content[1]
+---+
and then for each of those pointers, you allocate an array of int:
for ( size_t i = 0; i < rows; i++ )
mat.content[i] = calloc( 2, sizeof *mat.content[i] );
giving us
int ** int * int
+---+ +---+ +---+
mat.content: | | ---> | | mat.content[0] ---> | | mat.content[0][0]
+---+ +---+ +---+
| | mat.content[1] -+ | | mat.content[0][1]
+---+ | +---+
|
|
| +---+
+-> | | mat.content[1][0]
+---+
| | mat.content[1][1]
+---+
The expression mat.content has type int **, so the expression *mat.content has type int *; thus, sizeof *mat.content == sizeof (int *). Similarly, the expression mat.content[i] also has type int * (*p == p[0]), so *mat.content[i] has type int, so sizeof *mat.content[i] == sizeof (int).
Because of how array subscripting works, mat.content[i][j] works exactly the same way as if you had declared mat.content as a regular 2D array of int. It's just instead of all the rows being allocated in a single contiguous chunk, they're allocated piecemeal.
General rules:
T *p; // p is a pointer to T
T *ap[N]; // ap is an array of pointer to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function that returns pointer to T
T (*pf)(); // pf is a pointer to a function that returns T
T **p; // p is a pointer to a pointer to T
T ***p; // p is a pointer to a pointer to a pointer to T
const T *p; // p is a pointer to const T - you can write to p, but not *p
T const *p; // same as above
T * const p; // p is a const pointer to T - you can write to *p, but not to p
When used in an expression, the * "dereferences" the pointer - if you have a declaration like
int x;
int *p = &x;
the expression *p acts as kind of an alias for x:
*p = 10; // does the same thing as x = 10;
The object p stores the location of x, and the type of the expression p is int * (pointer to int). The expression *p is equivalent to the expression x - not only does it yield the value stored in x, you can write a new value to x through *p as shown above.
The declarations above give us this relationship:
p == &x // int * == int *
*p == x // int == int
The array subscript expression a[i] is defined as *(a + i) - given a starting address designated by a, offset i elements (not bytes!) from that address and dereference the result.
*p == *(p + 0) == p[0]
Arrays are not pointers, nor do they store a pointer to their first element. Unless it is the operand of the sizeof, _Alignof, 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, or "decay", to an expression of type "pointer to T" and the value of the expression will be the address of the first element. This is important - if you declare an array
int a[10];
a does not store an address to its first element; instead, any time the compiler sees the expression a outside of the contexts listed above, it will basically replace it with something equivalent to &a[0].
I have tried using int**(pointer to a pointer) and int*[](array of pointers) but i am unable to perform the task with pointer to an array.How can we use pointer to an array and malloc function to create an 2-d array in c.
Please provide a sample code:)
void *allocateMemory2DArray(size_t x, size_t y)
{
int (*array)[x][y];
array = malloc(sizeof(*array));
return array;
}
5d array
void *allocateMemory5DArray(size_t x, size_t y, size_t v, size_t q, size_t r)
{
int (*array)[x][y][z][q][r];
array = malloc(sizeof(*array));
return array;
}
So let’s start from the ground up.
The typical way to dynamically allocate an N-element array of T (for some arbitrary T) is
T *p = malloc( sizeof *p * N ); // sizeof *p == sizeof (T)
This allocates enough space for N objects of type T, with p pointing to the first element
T * T
+–––+ +–––+
p: | |–––––>| | p[0]
+–––+ +–––+
| | p[1]
+–––+
...
+–––+
| | p[N-1]
+–––+
Now, replace T with an array type - R [M]:
R (*p)[M] = malloc( sizeof *p * N );
This allocates enough space for N objects of type R [M] - IOW you’ve allocated an NxM array of R. p still points to the first element, it’s just that in this case the first element is an array in itself.
R (*)[M] R [M]
+–––+ +–––+
p: | |––––––>| | p[0][0]
+–––+ + - +
| | p[0][1]
+ - +
...
+ – +
| | p[0][M-1]
+––—+
| | p[1][0]
+ – +
| | p[1][1]
+ - +
...
+ – +
| | p[1][M-1]
+–––+
...
+ – +
| | p[N-1][M-1]
+–––+
You’d index into p like any regular 2d array.
You can extend this to higher-dimensioned arrays - replace R with another array type like Q [L]:
Q (*p)[M][L] = malloc( sizeof *p * N );
This allocates space for an NxMxL array, and again you’d index into it like any 3d array p[i][j][k].
The semantics are exactly the same in every case - you’re allocating space for N objects, it’s just that the types of the objects are different.
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 address1 and dereference the result2. 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.
Pointer arithmetic works in terms of objects, not bytes. If 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.
”But everyone says arrays are not pointers, how is 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.
int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
*matrix = malloc(20 * sizeof(int));
I just don't understand the concept of double pointers and how this translates to a two-dimensional array ( that is if it's true )
Thanks in advance.
What is being created here is not technically a 2D array but an array of pointers, each of which would contain the starting address of an array. This can then be indexed as if it were a "real" 2D array.
This line creates an array of 5 pointers to int:
matrix = malloc(5 * sizeof(int*));
The next line creates a single array 20 int:
*matrix = malloc(20 * sizeof(int));
This however is incomplete in terms of a 2D array because only one row was allocated. You need to loop through every element that matrix points to in order to create each row:
int **matrix, i;
matrix = malloc(5 * sizeof(int*));
for (i=0; i<5; i++) {
matrix[i] = malloc(20 * sizeof(int));
}
When you're done using this dynamic 2D array, you'll need to free the memory in the reverse order:
for (i=0; i<5; i++) {
free(matrix[i]);
}
free(matrix);
This differs from a real 2D array in a few ways. First, in a true 2D array all elements are contiguous in memory, where in this case the array of pointers and each row array are not.
The other difference is when being passed to a function you can't pass it the same way you'd pass a real 2D array.
For a simple 1D array, whether allocated at compile time or dynamically:
int a1[5];
int *a2 = malloc(5 * sizeof(int));
Both can be passed to a function like this:
void f(int *a);
But in the case of a 2D array:
int a[5][20];
It would need to be passed to a function like this:
void f(int a[5][20]);
Or equivalently:
void f(int (*a)[20]);
Whereas a dynamic 2D array needs to be passed to a function like this:
void f(int **a);
Some pictures might help.
Let's start with matrix, which is a pointer to pointer to int:
int **
+--------+
| matrix |---???
+--------+
After the first call to malloc, you have the following:
int ** int *
+--------+ +-----------+
| matrix |--->| matrix[0] |
+--------+ +-----------+
| matrix[1] |
+-----------+
| matrix[2] |
+-----------+
| matrix[3] |
+-----------+
| matrix[4] |
+-----------+
You've dynamically allocated space for 5 int * objects, and matrix points to the first one. After the second call to malloc, you have this (the expression *matrix is equivalent to matrix[0] - more on that below):
int ** int * int
+--------+ +-----------+ +---------------+
| matrix |--->| matrix[0] |--->| matrix[0][0] |
+--------+ +-----------+ +---------------+
| matrix[1] | | matrix[0][1] |
+-----------+ +---------------+
| matrix[2] | | matrix[0][2] |
+-----------+ +---------------+
| matrix[3] | ...
+-----------+ +---------------+
| matrix[4] | | matrix[0][19] |
+-----------+ +---------------+
You've dynamically allocated space for 20 int objects, and matrix[0] points to the first one.
So, in short - each matrix[i][j] is an int. Each matrix[i] points to matrix[i][0], so each matrix[i] must be a pointer to int, or int *. matrix points matrix[0], meaning matrix must be a pointer to int *, or int **.
Remember that the array subscript expression a[i] is defined as *(a + i) - given an address a, offset i elements (not bytes!) from that address and deference the result. Thus, *matrix is equivalent to *(matrix + 0), which is equivalent to matrix[0].
Now, what you have here is not a true 2D array - you have a sequence of pointers, each of which may point to the first of a sequence of int objects (or to nothing at all). The "rows" of the array will (most likely) not be adjacent in memory. In a true 2D array, all array elements will be contiguous. Given
int matrix[5][20];
elements will look like this:
+---------------+
| matrix[0][0] |
+---------------+
| matrix[0][1] |
+---------------+
...
+---------------+
| matrix[0][19] |
+---------------+
| matrix[1][0] |
+---------------+
| matrix[1][1] |
+---------------+
...
+---------------+
| matrix[4][19] |
+---------------+
EDIT
Some other key differences between a pointer-to-pointer and a 2D array. First, assume the following definitions:
int **ptr;
int matrix[ROWS][COLS];
The expression ptr has type int **. The expression matrix will "decay" from type int [ROWS][COLS] to type int (*)[COLS] (pointer to COLS-element array of int);
sizeof ptr gives the size of the pointer itself (4, 8, or some other number of bytes). sizeof matrix gives the size of the entire array in bytes (ROW * COLS * sizeof (int)).
The expressions &matrix, matrix, &matrix[0], and &matrix[0][0] will all yield the same value (the address of the first element of the array), although the types of the expressions will be different - int (*)[ROWS][COLS], int (*)[COLS], int (*)[COLS], and int *, respectively. The expressions &ptr, ptr, &ptr[0], and &ptr[0][0] will not all yield the same values - &ptr and &ptr[0][0] will be different values than ptr and &ptr[0], and the types of the expressions will be int ***, int **, int **, and int *.
I think you want the following:
int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
for (int i=0; i<5; i++)
matrix[i] = malloc(20 * sizeof(int));
Here you first allocate an array of pointers to rows. Then you allocate memory for each row.
if R is my rows number and C my column number
I initialize a pointer like this:
int * a = (int*) malloc(R*C*sizeof(int));
Then to access the second element in the second row I type:
a[1*c + 1]
I want to emulate a 2D arr.
How can I make a macro that will convert this: a[i][j] to this a[i*c + j]?
A macro can't read and convert square brackets. But you can write:
int (*b)[C] = (void *)a;
and then you can use b[i][j] which has the same meaning as a[i*C + j].
If you don't want a separate macro for every dynamic array that you might use, you will need something a bit more general. For example:
#define INDEX_2D(array, i, j, j_sz) array[ (i) * (j_sz) + (j) ]
Then you can use it like this:
INDEX_2D(my_array, row, col, C) = x;
printf("%d\n", INDEX_2D(my_array, row, col, C));
Still, this seems clumsy. If you can't use actual 2d arrays, why not just use straightforward indexing calculations, which actually seem more clear?
my_array[row * C + col] = x;
printf("%d\n", my_array[row * C + col]);
The preprocessor is not a good tool for faking 2D array access on a 1D array. Another approach would be to create an array of pointers into the 1D array, like so:
int *a = malloc( R * C * sizeof *a ); // do not cast the result of malloc!
int *b[] = { &a[0], &a[C], &a[2*C], ..., &a[(R-1) * C] };
The result is something like the following (assume R == 2 and C == 3):
+---+ +---+
b: | | b[0] -----> a: | | a[0]
+---+ +---+
| | b[1] ---+ | | a[1]
+---+ | +---+
| | | a[2]
| +---+
+----> | | a[3]
+---+
| | a[4]
+---+
| | a[5]
+---+
This way, you can use b[i][j] to access elements in a (b[i][j] == a[i * R + j]).