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];
}
Related
I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}
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) {...}.
I am trying to build two dimensional array by dynamically allocating. My question is that is it possible that its first dimension would take 100 values, then second dimension would take variable amount of values depending on my problem? If it is possible then how I would access it? How would I know the second dimension's boundary?
(See the comments in the code)
As a result you'll get an array such like the following:
// Create an array that will contain required variables of the required values
// which will help you to make each row of it's own lenght.
arrOfLengthOfRows[NUMBER_OF_ROWS] = {value_1, value_2, ..., value_theLast};
int **array;
array = malloc(N * sizeof(int *)); // `N` is the number of rows, as on the pic.
/*
if(array == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
// Here we make each row of it's own, individual length.
for(i = 0; i < N; i++) {
array[i] = malloc(arrOfLengthOfRows[i] * sizeof(int));
/*
if(array[i] == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
}
You can use array of 100 pointers:
int *arr[100];
then you can dynamically allocate memory to each of the 100 pointers separately of any size you want, however you have to remember how much memory (for each pointer) you have allocated, you cannot expect C compiler to remember it or tell it to you, i.e. sizeof will not work here.
To access any (allowed, within boundary) location you can simply use 2D array notation e.g. to access 5th location of memory allocated to 20th pointer you can use arr[20][5] or *(arr[20] + 5).
I believe the OP wants a single chunk of memory for the array, and is willing to fix one of the dimensions to get it. I frequently like to do this when coding in C as well.
We all used to be able to do double x[4][]; and the compiler would know what to do. But someone has apparently messed that up - maybe even for a good reason.
The following however still works and allows us to use large chunks of memory instead of having to do a lot of pointer management.
#include <stdio.h>
#include <stdlib.h>
// double x[4][];
struct foo {
double y[4];
} * x;
void
main(int ac, char * av[])
{
double * dp;
int max_x = 10;
int i;
x = calloc(max_x, sizeof(struct foo));
x[0].y[0] = 0.23;
x[0].y[1] = 0.45;
x[9].y[0] = 1.23;
x[9].y[1] = 1.45;
dp = x[9].y;
for (i = 0; i < 4; i++)
if (dp[i] > 0)
printf("%f\n", dp[i]);
}
The trick is to declare the fixed dimension in a struct. But keep in mind that the "first" dimension is the dynamic dimension and the "second" one is fixed. And this is the opposite of the old way ...
You will have to track the size of your dynamic dimension on your own - sizeof can't help you with that.
Using anonymous thingies you might even be able to git rid of 'y'.
Using a single pointer:
int *arr = (int *)malloc(r * c * sizeof(int));
/* how to access array elements */
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count; //count initialized as, int count=0;
Using pointer to a pointer:
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
In this case you can access array elements same as you access statically allocated array.
my row size is fixed but the column size keeps varying all the time.That's why I am thinking to use pointers for column level.But I am not sure how to use this feature in C.Please kindly help me.
int array[rows][columns]; //row size fixed but column size is not fixed.
If all but one dimension of your array are fixed, which is the situation that you describe, you can avoid using arrays of pointers: you could typedef a row as int[rows], and create an array of rows, like this:
typedef int row_t[rows];
Now you can pass around 2D arrays composed of row_t arrays like this:
int total(row_t array[], int len) {
int res = 0;
for (int c = 0 ; c != len ; c++) {
for (int r = 0 ; r != rows ; r++) {
res += array[r][c];
}
}
return res;
}
int main() {
row_t *matrix = malloc(columns*sizeof(row_t));
for (int c = 0 ; c != columns ; c++) {
for (int r = 0 ; r != rows ; r++) {
matrix[r][c] = r*r+c*c;
}
}
printf("%d\n", total(matrix, columns));
free(matrix);
return 0;
}
You need to declare an array of pointers. Like this:
int *array[rows];
Later, according to the need, allocate memory to each row. You can use malloc or calloc functions for this.
for(int i=0; i<rows; i++){
array[i] = (int *) malloc(columns * sizeof(int));
}
This method also allows one to have rows with varying sizes.
you cannot use variable in array dimensions so use pointer to pointers
int **array;
array = (int **)malloc(sizeof(int *) * rows);
for (int i = 0; i < rows; ++i) {
array[i] = (int *)malloc(sizeof(int) * columns);
for (int j = 0; j < columns; j++) {
array[i][j] = value;
}
}
and ofcourse do not forget to free it all
You would do this by having an array of int*, e.g.
int* array[row];
for (int i = 0; i < row; ++i)
array[i] = (int*)malloc(i * sizeof(int));
And then you can access the data the same as if it was static.
int val = array[myRow][myColumn];
You'll have to be sure to free the memory in the same pattern as you allocated it.
Since 13 years now C allows dynamic sizes in the declaration of arrays. This is called variable length array, VLA.
If you really have large arrays, this might explose your stack. But you can still allocate such a beast with malloc and have all the simplicity of a 2D array:
size_t n = SOME_COMPLICATED_VALUE;
size_t m = ANOTHER_ONE;
double (*A)[n] = malloc(double[m][n]);
If each row can have a different number of columns, then the general approach is to declare an array of pointers, and then for each row dynamically allocate the number of elements for that row:
int *array[ROWS];
array[i] = malloc(sizeof *array[i] * number_of_columns_for_row_i);
Note that when you are done, you'll have to free each row individually:
for (i = 0; i < ROWS; i++)
free(array[i]);
If all the rows have the same number of columns, but that number can change for each instance of the array, then you have several choices. If you're using a C99-compliant compiler, you can use a variable length array, where the array dimension isn't known until runtime:
int columns;
// get number of columns somehow
int array[ROWS][columns];
VLAs are handy, but have their limitations; they cannot be members of struct or union types, and they cannot be declared static or at file scope. The big advantage of this approach is that you don't have to worry about deallocating anything when you're done. The big disadvantage of this approach is that you may not have enough memory to satsify the request; the memory space available for auto variables is typically quite limited compared to memory for dynamically-allocated objects. Also, the latest revision of the language standard (C11) makes VLAs optional, so they may not be available in all implementations going forward.
Alternately, you could dynamically allocate the array like so:
int (*array)[ROWS];
int columns;
// get number of columns somehow
array = malloc(sizeof *array * columns);
Note that this time, array is a pointer to an array of int, not an array of pointers to int. The benefit of this approach is that the array memory is allocated contiguously, and free-ing the memory is as simple as writing
free(array);
The drawback is that if your array is really big or the dynamic memory pool is really fragmented, you may not have a large enough chunk of memory available to satisfy the request.
If you don't need all the rows to be allocated contiguously, then use the first approach that allocates each row individually; just use the same value for the number of columns:
int *array[ROWS];
int columns;
// get number of columns
for (i = 0; i < ROWS; i++)
array[i] = malloc(sizeof *array[i] * columns);
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];
}