C Pointer to Pointer Problems in Matrix Function - c

I know there are very similar questions, but I've read them and I don't understand what is going wrong or what exactly I haven't understood about pointers to pointers.
My teacher is using a "learning by doing" approach to pointers and it has left me with approximately 100 questions. Sometimes I just change things around until it compiles, but it really isn't becoming any more clear to me, so if someone could help clarify a few things, I'd really appreciate it.
struct Matrix {
int rows; // number of rows
int cols; // number of columns
double **data;
};
typedef struct Matrix Matrix;
The pointer to a pointer, is something like this, right?
double *row1 = (double *) malloc (n_cols*sizeof(double));
double *row2 = (double *) malloc (n_cols*sizeof(double));
double *row3 = (double *) malloc (n_cols*sizeof(double));
double *data[] = { row1, row2, row3};
Data is pointing to the row number which is pointing to the doubles in the rows.
Now I am supposed to make a constructor function that makes a Matrix with a 0 in every position returns a pointer to a Matrix.
Matrix *make_matrix(int n_rows, int n_cols) {
Matrix *m = xmalloc(sizeof(Matrix));
m->rows = n_rows;
m->cols = n_cols;
double **rows_and_columns = xmalloc(n_rows * n_cols * sizeof(double));
memset(rows_and_columns, 0, m->rows * m->cols * sizeof(double));
m->data = *rows_and_columns;
return m;
}
So I made a pointer for the matrix, then I assigned the values for the rows and columns. Then I got confused (although I am not sure how confused, because this part compiles). I made a pointer to pointer for the last element of the struct Matrix (**data). Since **rows_and_columns has to hold the rows and columns, I allocated xmalloc(n_rows * n_cols * sizeof(double)) memory to it. I then set the whole thing to 0 and assign it to data. I think this m->data = rows_and_columns; says that m points to data and since data is a pointer and rows_and_columns is a pointer, we'll align their addresses, so m->data will also point to a bunch of 0s? Or is this wrong? And I am returning m, because the output is Matrix * and the m will get the * upon output, correct?
The next step is to copy a matrix, at which point I got even more lost.
Matrix *copy_matrix(double *data, int n_rows, int n_cols) {
Matrix *m = make_matrix(n_rows, n_cols);
double *row = (double *) malloc (n_cols*sizeof(double));
int i = 0;
for (int j = 0; j < n_rows; j++) {
for (; i < n_cols; i++) {
row = (double *) malloc (n_cols*sizeof(double));
row [i] = data[i + j*n_cols];
}
m->data [j] = *row [i];
}
free(row);
return m;
}
So we are returning a pointer to a Matrix again. The input is now a pointer to double values, which I am assuming are the rows. First, I made a matrix. Then I made a pointer for a row with a n columns worth of memory (double *) malloc (n_cols*sizeof(double)).
This is where I got super confused. I was imagining **data the whole time as something like above (double *data[] = { row1, row2, row3};). So, I wanted to copy each row of *data into *row, then save that as an entry in **data, like data[0] = row0, but something isn't clicking with the pointers, because I am not allowed to assign m->data [j] = row [i];, because I'm assigning incompatible types by assigning double * from type double?

xmalloc() returns a void * pointer to single block of memory.
What you need is one block of pointers, serving as an conceptual table header row, holding pointers to other memory blocks which themselves contain the actual doubles.
double **columns -> [double *col0] [double *col1] [double *col2] ...
| | |
V V V
[double col_val0] [double col_val0] ...
[double col_val1] [double col_val1]
[double col_val2] [double col_val2]
... ...
A matrix allocation could look like this:
// Allocate the double pointer array:
double **matrix_rows = xmalloc(sizeof(double *) * column_count);
// Iterate over each double-pointer in the double-pointer-array allocated above.
for(int i = 0; i < column_count; i++) {
// Allocate a new double-array, and let current double-pointer point to it:
matrix_rows[i] = malloc(sizeof(double) * row_count);
// Initialize matrix cell, iterating over allocated values.
for(int j = 0; j < row_count; j++) {
// Accessing the i'th col and j'th cell.
matrix_rows[i][j] = 0.0;
}
}
A possible implementation of a matrix copy function could be done by iteratively copying individial cells. One way to do this is using a loop composition.
for(int col = 0; col < col_count; col++) {
for(int row = 0; row < row_count; row++) {
destination_matrix[col][row] = source_matrix[col][row];
}
}
To give some intuition where an n-pointer indirection could be used:
n = 1: Strings, an array of characters.
n = 2: Paragraph, holding lines of strings.
n = 3: An article, holding a list of paragraphs.
Please be aware of using two indirections is usually not something you want. It is usually more efficient to store data in a linear fashion and compute linear indices out of two-compoment vectors and the other way around, especially in the case of this matrix example.

If you want to represent a matrix as an array of pointers to rows you need to allocate memory both for the rows and for the array of pointers to rows. It is simpler to allocate the rows consecutively as a single block.
typedef struct
{
int n_rows;
int n_cols;
double **rows;
double *data;
} Matrix;
Matrix *matrix_new (int n_rows, int n_cols)
{
// allocate matrix
Matrix *m = malloc (sizeof(Matrix));
m->n_rows = n_rows;
m->n_cols = n_cols;
// allocate m->data
m->data = malloc (n_rows * n_cols * sizeof(double));
// allocate and fill m->rows
m->rows = malloc (n_rows * sizeof(double*));
for (int i = 0; i < n_rows; i++) {
m->rows[i] = &data[i * n_cols];
}
// set the matrix to 0
for (int i = 0; i < n_rows; i++) {
for (int j = 0; j < n_cols; j++) {
m->rows[i][j] = 0.0;
}
}
return m;
}
The purpose of the rows array it to give you the convenience of being able to refer to element i,j with m->rows[i][j] instead of m->data[i * m->n_cols + j].
To free the matrix, take the inverse steps:
void matrix_free (Matrix *m)
{
free (m->rows);
free (m->data);
free (m);
}
To copy you can simply allocate a matrix of the same size and copy element by element:
Matrix *matrix_copy (Matrix *m1)
{
Matrix *m2 = matrix_new (m1->n_rows, m1->n_cols);
for (int i = 0; i < m1->n_rows; i++) {
for (int j = 0; j < m1->n_cols; j++) {
m2->rows[i][j] = m1->rows[i][j];
}
}
return m2;
}
The important thing to note is that you must not copy the rows array since it is unique to each matrix.

It is important to understand the difference between pointers-to-pointers and multi-dimensional arrays.
What makes it extra confusing is that the same syntax is used for referencing individual elements: var[i][j] will reference element (i,j) of var regardless of if var is a pointer to pointer, double **var or a two-dimensional array, double var[22][43].
What really happens is not the same. A two-dimensional array is a contiguous memory block. A pointer to pointers is an array of pointers that point to the individual rows.
// Two-dimensional array
char var1[X1][X2];
int distance = &var[4][7] - &var[0][0]; // distance = 4*X2+7
// Pointer-to-pointer
char **var2 = malloc(X1 * sizeof(char*)); // Allocate memory for the pointers
for (i=0; i<X1; i++) var2[i] = malloc(X2); // Allocate memory for the actual data
int distance2 = &var2[4][7] - &var[0][0]; // This could result in anything, since the different rows aren't necessarily stored one after another.
The calculation of distance2 invokes undefined behaviour since the C standard doesn't cover pointer arithmetic on pointers that point to different memory blocks.
You want to use pointer-to-pointer. So you need to first allocate memory for an array of pointers and then for each array:
Matrix *make_matrix(int n_rows, int n_cols) {
Matrix *m = xmalloc(sizeof(Matrix));
int i, j;
m->rows = n_rows;
m->cols = n_cols;
m->data = xmalloc(n_rows * sizeof(double*));
for (i=0; i < n_; i++) {
m->data[i] = xmalloc(n_cols * sizeof(double));
for (j=0; j < n_cols; j++) {
m->data[i][j] = 0.0;
}
}
return m;
}
Don't assume that the double 0.0 will have all bits set to 0!
To copy a matrix:
Matrix *copy_matrix(Matrix *source) {
Matrix *m = make_matrix(source->n_rows, source->n_cols);
int i, j;
for (j = 0; j < n_rows; j++) {
for (i = 0; i < n_cols; i++) {
m->data[i][j] = source[i][j];
}
}
return m;
}

I'll backup a bit and start with the basics. Pointers are one of those things that are not difficult to understand technically, but require you to beat your head into the I want to understand pointers wall enough for them to sink in. You understand that a normal variable (for lack of better words) is just a variable that holds a direct-reference to an immediate value in memory.
int a = 5;
Here, a is a label to the memory address that holds the value 5.
A pointer on the other hand, does not directly-reference an immediate value like 5. Instead a pointer holds, as its value, the memory address where 5 is stored. You can also think of the difference this way. A normal variable holds a value, while a pointer holds the address where the value can be found.
For example, to declare a pointer 'b' to the memory address holding 5 above, you would do something like:
int *b = &a;
or equivalently:
int *b = NULL;
b = &a;
Where b is assigned the address of a. To return the value stored at the address held by a pointer, or to operate directly on the value stored at the address held by a pointer, you must dereference the pointer. e.g.
int c = *b; /* c now equals 5 */
*b = 7; /* a - the value at the address pointed to by b, now equals 7 */
Now fast forward to pointer-to-pointer-to-type and simulated 2D matricies. When you declare your pointer-to-pointer-to-type (e.g. int **array = NULL), you are declaring a pointer that points to a pointer-to-type. To be useful in simlated 2D arrays (matricies, etc.), you must delcare an array of the pointer-to-pointer-to-type:
int **array = NULL;
...
array = calloc (NUM, sizeof *array); /* creates 'NUM' pointer-to-pointer-to-int. */
You now have NUM pointers to pointers-to-int that you can allocate memory to hold however many int values and you will assign the starting address for the memory block holding those int values to the pointers you previously allocated. For example, let's say you were to allocate space for an array of 5 random int values (from 1 - 1000) to each of the NUM pointers you allocated above:
for (i = 0; i < NUM; i++) {
array[i] = calloc (5, sizeof **array);
for (j = 0; j < 5; j++)
array[i][j] = rand() % 1000 + 1;
}
You have now assigned each of your NUM pointers (to-pointer-to-int) the starting address in memory where 5 random int values are stored. So your array is now complete. Each of your original NUM pointers-to-pointer-to-int now points to the address for a block of memory holding 5 int values. You can access each value with array notation (e.g. array[i][j] or with pointer notation *(*(array + i) + j) )
How do you free the memory? In the reverse order you allocated (values, then pointers):
for (i = 0; i < NUM; i++)
free (array[i]);
free (array);
Note: calloc both allocates memory and initializes the memory to 0/nul. This is particularly useful for both the pointers and arrays when dealing with numeric values, and when dealing with an unknown number of rows of values to read. Not only does it prevent an inadvertent read from an uninitialized value, but it also allows you to iterate over your array of pointers with i = 0; while (array[i] != NULL) {...}.

Related

In C/C++: How can i implement a 2D int array using two single pointers (no use of **int)?

I am exploring pointer "mechanics" in C/C++. I try to understand if and how is possible to implement a 2D matrix using two pointers (one for "rows" and one for "columns") instead of a single double pointer. I am aware that a matrix with rows*columns number of values could be stored in memory sequentially, but i am looking to comprehend deeper the mechanics of pointers and eventually to implement a function similar to
int value=getValue(vectorNr,vectorValue)
that is able to "simulate" the construct
value=Matrix[vectorNr][vectorValue]
vectorPointer vectorValue
| AddressV1 |------|valAddr11 valAddr12 valAddr13 |
| AddressV2 |------|valAddr21 valAddr22 valAddr23 |
| AddressV3 |------|valAddr31 valAddr32 valAddr33 |
I tried to begin writing a code like this but I quickly get stuck on pointer arithmetic and address offsetting. I also might chose a very dirty approach so any comment is welcome.
CODE TO IMPLEMENT A 2D ARRAY WITH POINTERS (BUT NOT USING DOUBLE POINTERS). To avoid confusion between rows and columns I refer to "Vectors as rows" and "Columns as vector values"
int vectorsNumber = 3; //Number of Vectors
int valuesNumber = 3; //Number of values stored in one Vector
//Addresses of Vectors. Since Vectors holds a reference to set of values, vectorPointer will hold an address for every set.
void* vectorPointer = malloc(vectorsNumber *sizeof(void*));
//Populating the vectorPointer with the address generated by allocating memory for every set of values
for (int i = 0; i < vectorsNumber; i++)
{
vectorPointer = (int*)malloc(valuesNumber * sizeof(int)); //Values shall be of int types
vectorPointer++; //ILLEGAL since cannot perform arithmetic on pointers of type void. What do do??
}
//Restore the initial address. In any case...ILLEGAL arithmetic. What do do??
for (int i = 0; i < vectorsNumber; i++)
{
vectorPointer--; //Restore the initial address. In any case...ILLEGAL arithmetic.
}
//Declaring the pointer to hold the address of one value. Memory was already allocated before
int* valueAddress;
for (int j = 0; j < vectorsNumber; j++)
{
//Getting the address of the first value of the first Vector
valueAddress = (int*)vectorPointer; //Is this casting valid in C language?
//Populating the value with whatever operation
for (int k = 0; k < valuesNumber; k++)
{
*valueAddress = (k + 1)*(j + 1); //populate the Vector with int values
}
vectorPointer++; //Switch to next Vector.ILLEGAL arithmetic
}
Actually, you only need one pointer. One way of doing it is by allocating enough memory to hold all the values, and then have functions that map the x/y values in the array to the respective memory location. Assume we want those to be the dimensions and our array variable:
int dimX = 10, dimY = 5;
int *array;
You can set a value this way:
void arraySet(int value, int x, int y) {
array[x + dimX * y] = value;
}
And get a value this way:
int arrayGet(int x, int y) {
return array[x + dimX * y];
}
Allocate the memory beforehand such as in the main function:
array = malloc(sizeof(int)*dimX*dimY);
Use it like this:
arraySet(123, 9, 3); // sets the value of [9, 3] to 123
printf("Memory at 9, 3 is %d\n", arrayGet(9, 3));
This "two pointers" idea doesn't make any sense and the code you posted cannot be salvaged. What you should do instead is to use a pointer to a 2D array:
int (*ptr)[x][y] = malloc(sizeof *ptr);
...
free(ptr);
That's it. However, a pointer to a 2D array is cumbersome, since we have to de-reference it before accessing the actual array. That is, we'd end up writing (*ptr)[i][j] = ...; which is ugly.
To dodge this, we can instead still allocate a 2D array, but instead of pointing at "the whole array", we point at the first element, which is a 1D array:
int (*ptr)[y] = malloc( sizeof(int[x][y]) );
...
ptr[i][j] = ... ; // more convenient syntax for access
...
free(ptr);
More info: Correctly allocating multi-dimensional arrays
You can simulate int a[2][3]; with
one dimensional array and index computing:
int* matrix = (int*) malloc(6 * sizeof(int));
int get_matrix_2_3(int* matrix, int i, int j) { return matrix[3 * i + j]; }
2-dimensional array:
int** matrix = (int**) malloc(2 * sizeof(int*));
for (int i = 0; i != 2; ++i) {
matrix[i] = (int*) malloc(3 * sizeof(int));
}
matrix[1][2] = 42;

Dynamically creating a 2 dimensional array of pointers in c [duplicate]

Does someone know how I can use dynamically allocated multi-dimensional arrays using C? Is that possible?
Since C99, C has 2D arrays with dynamical bounds. If you want to avoid that such beast are allocated on the stack (which you should), you can allocate them easily in one go as the following
double (*A)[n] = malloc(sizeof(double[n][n]));
and that's it. You can then easily use it as you are used for 2D arrays with something like A[i][j]. And don't forget that one at the end
free(A);
Randy Meyers wrote series of articles explaining variable length arrays (VLAs).
With dynamic allocation, using malloc:
int** x;
x = malloc(dimension1_max * sizeof(*x));
for (int i = 0; i < dimension1_max; i++) {
x[i] = malloc(dimension2_max * sizeof(x[0]));
}
//Writing values
x[0..(dimension1_max-1)][0..(dimension2_max-1)] = Value;
[...]
for (int i = 0; i < dimension1_max; i++) {
free(x[i]);
}
free(x);
This allocates an 2D array of size dimension1_max * dimension2_max. So, for example, if you want a 640*480 array (f.e. pixels of an image), use dimension1_max = 640, dimension2_max = 480. You can then access the array using x[d1][d2] where d1 = 0..639, d2 = 0..479.
But a search on SO or Google also reveals other possibilities, for example in this SO question
Note that your array won't allocate a contiguous region of memory (640*480 bytes) in that case which could give problems with functions that assume this. So to get the array satisfy the condition, replace the malloc block above with this:
int** x;
int* temp;
x = malloc(dimension1_max * sizeof(*x));
temp = malloc(dimension1_max * dimension2_max * sizeof(x[0]));
for (int i = 0; i < dimension1_max; i++) {
x[i] = temp + (i * dimension2_max);
}
[...]
free(temp);
free(x);
Basics
Arrays in c are declared and accessed using the [] operator. So that
int ary1[5];
declares an array of 5 integers. Elements are numbered from zero so ary1[0] is the first element, and ary1[4] is the last element. Note1: There is no default initialization, so the memory occupied by the array may initially contain anything. Note2: ary1[5] accesses memory in an undefined state (which may not even be accessible to you), so don't do it!
Multi-dimensional arrays are implemented as an array of arrays (of arrays (of ... ) ). So
float ary2[3][5];
declares an array of 3 one-dimensional arrays of 5 floating point numbers each. Now ary2[0][0] is the first element of the first array, ary2[0][4] is the last element of the first array, and ary2[2][4] is the last element of the last array. The '89 standard requires this data to be contiguous (sec. A8.6.2 on page 216 of my K&R 2nd. ed.) but seems to be agnostic on padding.
Trying to go dynamic in more than one dimension
If you don't know the size of the array at compile time, you'll want to dynamically allocate the array. It is tempting to try
double *buf3;
buf3 = malloc(3*5*sizeof(double));
/* error checking goes here */
which should work if the compiler does not pad the allocation (stick extra space between the one-dimensional arrays). It might be safer to go with:
double *buf4;
buf4 = malloc(sizeof(double[3][5]));
/* error checking */
but either way the trick comes at dereferencing time. You can't write buf[i][j] because buf has the wrong type. Nor can you use
double **hdl4 = (double**)buf;
hdl4[2][3] = 0; /* Wrong! */
because the compiler expects hdl4 to be the address of an address of a double. Nor can you use double incomplete_ary4[][]; because this is an error;
So what can you do?
Do the row and column arithmetic yourself
Allocate and do the work in a function
Use an array of pointers (the mechanism qrdl is talking about)
Do the math yourself
Simply compute memory offset to each element like this:
for (i=0; i<3; ++i){
for(j=0; j<3; ++j){
buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about
padding in this case */
}
}
Allocate and do the work in a function
Define a function that takes the needed size as an argument and proceed as normal
void dary(int x, int y){
double ary4[x][y];
ary4[2][3] = 5;
}
Of course, in this case ary4 is a local variable and you can not return it: all the work with the array must be done in the function you call of in functions that it calls.
An array of pointers
Consider this:
double **hdl5 = malloc(3*sizeof(double*));
/* Error checking */
for (i=0; i<3; ++i){
hdl5[i] = malloc(5*sizeof(double))
/* Error checking */
}
Now hdl5 points to an array of pointers each of which points to an array of doubles. The cool bit is that you can use the two-dimensional array notation to access this structure---hdl5[0][2] gets the middle element of the first row---but this is none-the-less a different kind of object than a two-dimensional array declared by double ary[3][5];.
This structure is more flexible then a two dimensional array (because the rows need not be the same length), but accessing it will generally be slower and it requires more memory (you need a place to hold the intermediate pointers).
Note that since I haven't setup any guards you'll have to keep track of the size of all the arrays yourself.
Arithmetic
c provides no support for vector, matrix or tensor math, you'll have to implement it yourself, or bring in a library.
Multiplication by a scaler and addition and subtraction of arrays of the same rank are easy: just loop over the elements and perform the operation as you go. Inner products are similarly straight forward.
Outer products mean more loops.
If you know the number of columns at compile time, it's pretty simple:
#define COLS ...
...
size_t rows;
// get number of rows
T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T
You can treat ap like any 2D array:
ap[i][j] = x;
When you're done you deallocate it as
free(ap);
If you don't know the number of columns at compile time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, it's still pretty simple:
size_t rows;
size_t cols;
// get rows and cols
T (*ap)[cols] = malloc(sizeof *ap * rows);
...
ap[i][j] = x;
...
free(ap);
If you don't know the number of columns at compile time and you're working with a version of C that doesn't support variable-length arrays, then you'll need to do something different. If you need all of the elements to be allocated in a contiguous chunk (like a regular array), then you can allocate the memory as a 1D array, and compute a 1D offset:
size_t rows, cols;
// get rows and columns
T *ap = malloc(sizeof *ap * rows * cols);
...
ap[i * rows + j] = x;
...
free(ap);
If you don't need the memory to be contiguous, you can follow a two-step allocation method:
size_t rows, cols;
// get rows and cols
T **ap = malloc(sizeof *ap * rows);
if (ap)
{
size_t i = 0;
for (i = 0; i < cols; i++)
{
ap[i] = malloc(sizeof *ap[i] * cols);
}
}
ap[i][j] = x;
Since allocation was a two-step process, deallocation also needs to be a two-step process:
for (i = 0; i < cols; i++)
free(ap[i]);
free(ap);
malloc will do.
int rows = 20;
int cols = 20;
int *array;
array = malloc(rows * cols * sizeof(int));
Refer the below article for help:-
http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf
Here is working code that defines a subroutine make_3d_array to allocate a multidimensional 3D array with N1, N2 and N3 elements in each dimension, and then populates it with random numbers. You can use the notation A[i][j][k] to access its elements.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Method to allocate a 2D array of floats
float*** make_3d_array(int nx, int ny, int nz) {
float*** arr;
int i,j;
arr = (float ***) malloc(nx*sizeof(float**));
for (i = 0; i < nx; i++) {
arr[i] = (float **) malloc(ny*sizeof(float*));
for(j = 0; j < ny; j++) {
arr[i][j] = (float *) malloc(nz * sizeof(float));
}
}
return arr;
}
int main(int argc, char *argv[])
{
int i, j, k;
size_t N1=10,N2=20,N3=5;
// allocates 3D array
float ***ran = make_3d_array(N1, N2, N3);
// initialize pseudo-random number generator
srand(time(NULL));
// populates the array with random numbers
for (i = 0; i < N1; i++){
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
ran[i][j][k] = ((float)rand()/(float)(RAND_MAX));
}
}
}
// prints values
for (i=0; i<N1; i++) {
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
printf("A[%d][%d][%d] = %f \n", i,j,k,ran[i][j][k]);
}
}
}
free(ran);
}
There's no way to allocate the whole thing in one go. Instead, create an array of pointers, then, for each pointer, create the memory for it. For example:
int** array;
array = (int**)malloc(sizeof(int*) * 50);
for(int i = 0; i < 50; i++)
array[i] = (int*)malloc(sizeof(int) * 50);
Of course, you can also declare the array as int* array[50] and skip the first malloc, but the second set is needed in order to dynamically allocate the required storage.
It is possible to hack a way to allocate it in a single step, but it would require a custom lookup function, but writing that in such a way that it will always work can be annoying. An example could be L(arr,x,y,max_x) arr[(y)*(max_x) + (x)], then malloc a block of 50*50 ints or whatever and access using that L macro, e.g.
#define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)]
int dim_x = 50;
int dim_y = 50;
int* array = malloc(dim_x*dim_y*sizeof(int));
int foo = L(array, 4, 6, dim_x);
But that's much nastier unless you know the effects of what you're doing with the preprocessor macro.
int rows, columns;
/* initialize rows and columns to the desired value */
arr = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
{
arr[i] = (int*)malloc(cols*sizeof(int));
}
// use new instead of malloc as using malloc leads to memory leaks
`enter code here
int **adj_list = new int*[rowsize];
for(int i = 0; i < rowsize; ++i)
{
adj_list[i] = new int[colsize];
}

How to declare pointer and allocate memory a two-dimensional array and pass to a function

I want to declare the correct pointer and allocate memory for a two-dimensional array, and correctly pass to a function. I am having trouble getting this to work properly and need help.
Here is my code:
double **podrucje;
podrucje=(double **) malloc (sizeof (double *) *123);
for (i=0;i<(123);i++)
{
podrucje[i]=(double *) malloc (sizeof (double) * 11);
}
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
But this code doesnt work, it messes up whole my program. So i decided to give up on dynamic allocation and use this:
double podrucje[123][11]={0};
But i dont know how to send it and use it in function...
memset works on per byte basis.
double **podrucje = (double **) malloc (sizeof (double *) * 123);
for (i = 0; i < 123; i++)
{
podrucje[i] = (double *) malloc (sizeof (double) * 11);
memset(podrucje[i], 0, sizeof(double) * 11);
}
if you want to pass it just declare it as such
void function(double podrucje[123][11]) {
...
}
You're best off to use malloc, but allocate the whole array on your second line, so it all gets allocated in contiguous memory. So
podrucje = (double*) malloc (sizeof (double) * 123 * 11);
Then the first loop can go away too. And it looks like you're initializing the array to 0 -- in that case, use calloc instead of malloc, eliminating the second loop.
To index into the array, use things like
double myitem = podrucje [11 * row + col];
You should of course use a define or similar to keep the use of 11 consistent, but that's not the point of this answer.
Write the function argument the same way you wrote the variable definition:
void myfunc(double podrucje[123][11])
{
...
}
double podrucje[123][11];
myfunc(podrucje);
Note that the array is passed "by reference" rather than being copied.
In the following code snippet,
podrucje[i]=(double *) malloc (sizeof (double) * 11);
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
1) You dont need the extra parenthesis against the numbers 123 and 11
The for loop can be as follows,
for (i = 0; i < 123; i++)
2) Instead of using 123 and 11. Try to define a MACRO and use that instead.
Advantage: The code becomes independent of special numbers and is easily maintainable. Especially in the cases of larger code base.
3) If you read the code, podrucje[i] is allocated a memory of 11 doubles But when you memset you are setting it for only 10 doubles while the last one may or may not consist of garbage. Use calloc here, It not only allocated memory but also initializes the same.
podrucje[i]=(double *) calloc(11,sizeof(double));
Also It could be more helpful if you could tell How exactly is it screwing up your code ?
Example, Code Snippet could help more than just stating its screwing up.
It helps others to investigate and solve the issue.
If you have a modern C compiler (C99 would do) you can even declare real 2D matrices with variable sizes. You don't need to fall back to this awful emulation with pointers.
void myfunc(size_t n, size_t m, double podrucje[n][m])
{
...
}
double (*podrucje)[n] = malloc(sizeof(double[n][m]));
myfunc(n, m, podrucje);
For the function you just have to ensure that the declarations of n and m come first, before the matrix.
There are several ways to dynamically allocate memory for an NxM array. Here are two:
You can declare a pointer to an M-element array, and then malloc N instances of it:
double (*podrucje)[11] = malloc(sizeof *podrucje * 123);
As of C89, you don't need to cast the result of malloc, and the practice is discouraged. Also, note that the operand to sizeof is the expression *podrucje; this gives me the same result as sizeof (double) * 11.
You would index this array as podrucje[i][j] like any other 2D array. podrucje[i] implicitly dereferences the pointer (remember that a[i] is equivalent to *(a + i)) so you don't have to do anything funky with it.
You would use it in a function as follows:
void init(double (*podrucje)[11], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 11; j++)
podrucje[i][j] = 0.0;
}
which would be called as
init(podrucje, 123);
The drawback to this method is that the function can only operate on Nx11 arrays; if you're using a C99 compiler or a C2011 compiler that supports variable length arrays, you could specify the number of columns as a runtime variable:
void foo(void)
{
size_t rows = 123, cols = 11;
double (*podrucje)[cols] = malloc(sizeof *podrucje * rows);
if (podrucje)
init(cols, podrucje, rows);
...
}
// cols must be declared before it can be used
// in an array declarator
//
void init(size_t cols, double(*podrucje)[cols], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're done with the array, deallocate it as follows:
free(podrucje);
The other approach is to allocate each row separately, as follows:
size_t rows = 123, cols = 11;
double **podrucje = malloc(sizeof *podrucje * rows);
if (!podrucje)
{
// malloc failed; handle allocation error here
}
else
{
size_t i;
for (i = 0; i < rows; i++)
{
podrucje[i] = malloc(sizeof *podrucje[i] * cols);
if (!podrucje[i])
{
// malloc failed; handle allocation error here
}
}
}
And you would use it in a function as follows:
void foo()
{
double **podrucje;
// allocate array as above
init(foo, rows, cols);
...
}
void init(double **podrucje, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're finished with the array, deallocate it as follows:
for(i = 0; i < rows; i++)
free(podrucje[i]);
free(podrucje);
The first method allocates memory as a single, contiguous block; the second allocates it in a series of smaller, discontinuous chunks. If your array is especially big or your heap especially fragmented, the first method may fail where the second will succeed. If you're working with a compiler that doesn't support variable-length arrays, the first method is much less flexible, because the number of columns must be specified at compile time.
How could the same indexing method work for both forms?
In the first case, each podrucje[i] is an 11-element array of double; indexing it with j works like any other array. In the second case, each podrucje[i] is a pointer to double. Since a[i] is evaluated as *(a + i), array indexing works on pointer expressions just as well as array expressions.
int print_func(char((*p)[26])[10])
{
int i = 0;
for (i=0; i < 26 ; i++) {
fprintf(stderr, "%02d:%.*s\n", i, 10, p[0][i]);
}
return (0);
}
int main(void)
{
int nrow = 26;
int ncol = 10;
char((*p)[26])[10] = (char((*)[26])[10])(0);
char(*q)[10];
char c = 'a';
int i = 0;
p = (char((*)[26])[10])malloc(sizeof(char) * nrow * ncol);
if ((char((*)[26])[10])0 == p) {
return (-1);
}
for (i=0, q=p[0]; i < nrow ; i++) {
memset(q, c, sizeof(char) * ncol);
c++;
q++;
}
for (i=0,q=p[0] ; i < nrow ; i++) {
fprintf(stderr, "%.*s\n", 10, q);
q++;
}
p[0][8][0]='z';
getchar();
print_func(p);
return (0);
}

Using malloc for allocation of multi-dimensional arrays with different row lengths

I have the following C code :
int *a;
size_t size = 2000*sizeof(int);
a = malloc(size);
which works fine. But if I have the following :
char **b = malloc(2000*sizeof *b);
where every element of b has different length.
How is it possible to do the same thing for b as i did for a; i.e. the following code would hold correct?
char *c;
size_t size = 2000*sizeof(char *);
c = malloc(size);
First, you need to allocate array of pointers like char **c = malloc( N * sizeof( char* )), then allocate each row with a separate call to malloc, probably in the loop:
/* N is the number of rows */
/* note: c is char** */
if (( c = malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }
for ( i = 0; i < N; i++ )
{
/* x_i here is the size of given row, no need to
* multiply by sizeof( char ), it's always 1
*/
if (( c[i] = malloc( x_i )) == NULL )
{ /* error */ }
/* probably init the row here */
}
/* access matrix elements: c[i] give you a pointer
* to the row array, c[i][j] indexes an element
*/
c[i][j] = 'a';
If you know the total number of elements (e.g. N*M) you can do this in a single allocation.
The typical form for dynamically allocating an NxM array of type T is
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * M);
}
}
If each element of the array has a different length, then replace M with the appropriate length for that element; for example
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * length_for_this_element);
}
}
Equivalent memory allocation for char a[10][20] would be as follows.
char **a;
a=malloc(10*sizeof(char *));
for(i=0;i<10;i++)
a[i]=malloc(20*sizeof(char));
I hope this looks simple to understand.
The other approach would be to allocate one contiguous chunk of memory comprising header block for pointers to rows as well as body block to store actual data in rows. Then just mark up memory by assigning addresses of memory in body to the pointers in header on per-row basis. It would look like follows:
int** 2dAlloc(int rows, int* columns) {
int header = rows * sizeof(int*);
int body = 0;
for(int i=0; i<rows; body+=columnSizes[i++]) {
}
body*=sizeof(int);
int** rowptr = (int**)malloc(header + body);
int* buf = (int*)(rowptr + rows);
rowptr[0] = buf;
int k;
for(k = 1; k < rows; ++k) {
rowptr[k] = rowptr[k-1] + columns[k-1];
}
return rowptr;
}
int main() {
// specifying column amount on per-row basis
int columns[] = {1,2,3};
int rows = sizeof(columns)/sizeof(int);
int** matrix = 2dAlloc(rows, &columns);
// using allocated array
for(int i = 0; i<rows; ++i) {
for(int j = 0; j<columns[i]; ++j) {
cout<<matrix[i][j]<<", ";
}
cout<<endl;
}
// now it is time to get rid of allocated
// memory in only one call to "free"
free matrix;
}
The advantage of this approach is elegant freeing of memory and ability to use array-like notation to access elements of the resulting 2D array.
If every element in b has different lengths, then you need to do something like:
int totalLength = 0;
for_every_element_in_b {
totalLength += length_of_this_b_in_bytes;
}
return malloc(totalLength);
I think a 2 step approach is best, because c 2-d arrays are just and array of arrays. The first step is to allocate a single array, then loop through it allocating arrays for each column as you go. This article gives good detail.
2-D Array Dynamic Memory Allocation
int **a,i;
// for any number of rows & columns this will work
a = malloc(rows*sizeof(int *));
for(i=0;i<rows;i++)
*(a+i) = malloc(cols*sizeof(int));
malloc does not allocate on specific boundaries, so it must be assumed that it allocates on a byte boundary.
The returned pointer can then not be used if converted to any other type, since accessing that pointer will probably produce a memory access violation by the CPU, and the application will be immediately shut down.

How do I work with dynamic multi-dimensional arrays in C?

Does someone know how I can use dynamically allocated multi-dimensional arrays using C? Is that possible?
Since C99, C has 2D arrays with dynamical bounds. If you want to avoid that such beast are allocated on the stack (which you should), you can allocate them easily in one go as the following
double (*A)[n] = malloc(sizeof(double[n][n]));
and that's it. You can then easily use it as you are used for 2D arrays with something like A[i][j]. And don't forget that one at the end
free(A);
Randy Meyers wrote series of articles explaining variable length arrays (VLAs).
With dynamic allocation, using malloc:
int** x;
x = malloc(dimension1_max * sizeof(*x));
for (int i = 0; i < dimension1_max; i++) {
x[i] = malloc(dimension2_max * sizeof(x[0]));
}
//Writing values
x[0..(dimension1_max-1)][0..(dimension2_max-1)] = Value;
[...]
for (int i = 0; i < dimension1_max; i++) {
free(x[i]);
}
free(x);
This allocates an 2D array of size dimension1_max * dimension2_max. So, for example, if you want a 640*480 array (f.e. pixels of an image), use dimension1_max = 640, dimension2_max = 480. You can then access the array using x[d1][d2] where d1 = 0..639, d2 = 0..479.
But a search on SO or Google also reveals other possibilities, for example in this SO question
Note that your array won't allocate a contiguous region of memory (640*480 bytes) in that case which could give problems with functions that assume this. So to get the array satisfy the condition, replace the malloc block above with this:
int** x;
int* temp;
x = malloc(dimension1_max * sizeof(*x));
temp = malloc(dimension1_max * dimension2_max * sizeof(x[0]));
for (int i = 0; i < dimension1_max; i++) {
x[i] = temp + (i * dimension2_max);
}
[...]
free(temp);
free(x);
Basics
Arrays in c are declared and accessed using the [] operator. So that
int ary1[5];
declares an array of 5 integers. Elements are numbered from zero so ary1[0] is the first element, and ary1[4] is the last element. Note1: There is no default initialization, so the memory occupied by the array may initially contain anything. Note2: ary1[5] accesses memory in an undefined state (which may not even be accessible to you), so don't do it!
Multi-dimensional arrays are implemented as an array of arrays (of arrays (of ... ) ). So
float ary2[3][5];
declares an array of 3 one-dimensional arrays of 5 floating point numbers each. Now ary2[0][0] is the first element of the first array, ary2[0][4] is the last element of the first array, and ary2[2][4] is the last element of the last array. The '89 standard requires this data to be contiguous (sec. A8.6.2 on page 216 of my K&R 2nd. ed.) but seems to be agnostic on padding.
Trying to go dynamic in more than one dimension
If you don't know the size of the array at compile time, you'll want to dynamically allocate the array. It is tempting to try
double *buf3;
buf3 = malloc(3*5*sizeof(double));
/* error checking goes here */
which should work if the compiler does not pad the allocation (stick extra space between the one-dimensional arrays). It might be safer to go with:
double *buf4;
buf4 = malloc(sizeof(double[3][5]));
/* error checking */
but either way the trick comes at dereferencing time. You can't write buf[i][j] because buf has the wrong type. Nor can you use
double **hdl4 = (double**)buf;
hdl4[2][3] = 0; /* Wrong! */
because the compiler expects hdl4 to be the address of an address of a double. Nor can you use double incomplete_ary4[][]; because this is an error;
So what can you do?
Do the row and column arithmetic yourself
Allocate and do the work in a function
Use an array of pointers (the mechanism qrdl is talking about)
Do the math yourself
Simply compute memory offset to each element like this:
for (i=0; i<3; ++i){
for(j=0; j<3; ++j){
buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about
padding in this case */
}
}
Allocate and do the work in a function
Define a function that takes the needed size as an argument and proceed as normal
void dary(int x, int y){
double ary4[x][y];
ary4[2][3] = 5;
}
Of course, in this case ary4 is a local variable and you can not return it: all the work with the array must be done in the function you call of in functions that it calls.
An array of pointers
Consider this:
double **hdl5 = malloc(3*sizeof(double*));
/* Error checking */
for (i=0; i<3; ++i){
hdl5[i] = malloc(5*sizeof(double))
/* Error checking */
}
Now hdl5 points to an array of pointers each of which points to an array of doubles. The cool bit is that you can use the two-dimensional array notation to access this structure---hdl5[0][2] gets the middle element of the first row---but this is none-the-less a different kind of object than a two-dimensional array declared by double ary[3][5];.
This structure is more flexible then a two dimensional array (because the rows need not be the same length), but accessing it will generally be slower and it requires more memory (you need a place to hold the intermediate pointers).
Note that since I haven't setup any guards you'll have to keep track of the size of all the arrays yourself.
Arithmetic
c provides no support for vector, matrix or tensor math, you'll have to implement it yourself, or bring in a library.
Multiplication by a scaler and addition and subtraction of arrays of the same rank are easy: just loop over the elements and perform the operation as you go. Inner products are similarly straight forward.
Outer products mean more loops.
If you know the number of columns at compile time, it's pretty simple:
#define COLS ...
...
size_t rows;
// get number of rows
T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T
You can treat ap like any 2D array:
ap[i][j] = x;
When you're done you deallocate it as
free(ap);
If you don't know the number of columns at compile time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, it's still pretty simple:
size_t rows;
size_t cols;
// get rows and cols
T (*ap)[cols] = malloc(sizeof *ap * rows);
...
ap[i][j] = x;
...
free(ap);
If you don't know the number of columns at compile time and you're working with a version of C that doesn't support variable-length arrays, then you'll need to do something different. If you need all of the elements to be allocated in a contiguous chunk (like a regular array), then you can allocate the memory as a 1D array, and compute a 1D offset:
size_t rows, cols;
// get rows and columns
T *ap = malloc(sizeof *ap * rows * cols);
...
ap[i * rows + j] = x;
...
free(ap);
If you don't need the memory to be contiguous, you can follow a two-step allocation method:
size_t rows, cols;
// get rows and cols
T **ap = malloc(sizeof *ap * rows);
if (ap)
{
size_t i = 0;
for (i = 0; i < cols; i++)
{
ap[i] = malloc(sizeof *ap[i] * cols);
}
}
ap[i][j] = x;
Since allocation was a two-step process, deallocation also needs to be a two-step process:
for (i = 0; i < cols; i++)
free(ap[i]);
free(ap);
malloc will do.
int rows = 20;
int cols = 20;
int *array;
array = malloc(rows * cols * sizeof(int));
Refer the below article for help:-
http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf
Here is working code that defines a subroutine make_3d_array to allocate a multidimensional 3D array with N1, N2 and N3 elements in each dimension, and then populates it with random numbers. You can use the notation A[i][j][k] to access its elements.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Method to allocate a 2D array of floats
float*** make_3d_array(int nx, int ny, int nz) {
float*** arr;
int i,j;
arr = (float ***) malloc(nx*sizeof(float**));
for (i = 0; i < nx; i++) {
arr[i] = (float **) malloc(ny*sizeof(float*));
for(j = 0; j < ny; j++) {
arr[i][j] = (float *) malloc(nz * sizeof(float));
}
}
return arr;
}
int main(int argc, char *argv[])
{
int i, j, k;
size_t N1=10,N2=20,N3=5;
// allocates 3D array
float ***ran = make_3d_array(N1, N2, N3);
// initialize pseudo-random number generator
srand(time(NULL));
// populates the array with random numbers
for (i = 0; i < N1; i++){
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
ran[i][j][k] = ((float)rand()/(float)(RAND_MAX));
}
}
}
// prints values
for (i=0; i<N1; i++) {
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
printf("A[%d][%d][%d] = %f \n", i,j,k,ran[i][j][k]);
}
}
}
free(ran);
}
There's no way to allocate the whole thing in one go. Instead, create an array of pointers, then, for each pointer, create the memory for it. For example:
int** array;
array = (int**)malloc(sizeof(int*) * 50);
for(int i = 0; i < 50; i++)
array[i] = (int*)malloc(sizeof(int) * 50);
Of course, you can also declare the array as int* array[50] and skip the first malloc, but the second set is needed in order to dynamically allocate the required storage.
It is possible to hack a way to allocate it in a single step, but it would require a custom lookup function, but writing that in such a way that it will always work can be annoying. An example could be L(arr,x,y,max_x) arr[(y)*(max_x) + (x)], then malloc a block of 50*50 ints or whatever and access using that L macro, e.g.
#define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)]
int dim_x = 50;
int dim_y = 50;
int* array = malloc(dim_x*dim_y*sizeof(int));
int foo = L(array, 4, 6, dim_x);
But that's much nastier unless you know the effects of what you're doing with the preprocessor macro.
int rows, columns;
/* initialize rows and columns to the desired value */
arr = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
{
arr[i] = (int*)malloc(cols*sizeof(int));
}
// use new instead of malloc as using malloc leads to memory leaks
`enter code here
int **adj_list = new int*[rowsize];
for(int i = 0; i < rowsize; ++i)
{
adj_list[i] = new int[colsize];
}

Resources