I create a 2D array in C as follows:
int **arr;
arr = malloc(rows * sizeof(int *));
for (i = 0; i < rows; i++)
arr[i] = malloc(cols * sizeof(int));
Now, I call:
func(arr)
In the function func, how do I calculate the row and column dimensions?
You can't calculate it - arr is just a pointer to a pointer, there is no more information associated with it (as with all C arrays). You have to pass the dimensions as separate arguments.
You can't. You have to pass the dimensions along with your array to the function func(arr).
you can't (the beauty of C). (and don't try using sizeof, because that will only give you the size of the pointer) If another function needs to know the dimensions of the array, you'll have to pass along those parameters (height and width) as arguments along with the array pointer.
A workaround for this would be to not use an array directly, but instead have a struct like this:
struct table{
int ** arr;
int rows;
int columns;
}
You can then have a function which creates instances of table that takes the number of rows and columns, and handles the allocation.
As everyone else has said, you can't. However, you may find it useful to create a structure to contain the row, column and pointer all together. This will allow you to say:
typedef struct {
int rows;
int cols;
int **data;
} myDataType;
...
foo(myData);
void foo(myDataType myData) {
for( i = 0; i < myData.rows; i++) {
for( j = 0; j < myData.cols; j++ ) {
printf("%d,%d: %d\n", i, j, myData.data[i][j]);
}
}
}
(I apologize if my syntax is slightly off; Perl, Java, C# and a little Ruby are jockying for elbow-space.)
Related
I'm attempting to create a dynamic Matrix with functions, but first I decided to segment the assignment so that I know everything works as it should. But the creation is not working.
I tried moving the parentheses, using different values, but it always crashes when i=2
int rows=4;
int columns=4;
int cont=1;
int ** Mat;
Mat=(int**)malloc(rows*columns*sizeof(int));
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
printf("%d",i);
*(*(Mat+i)+j)=cont++;
}
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
printf("%2d ", *(*(Mat+i)+j) ); /* a[i][j] */
}
printf("\n");
}
I don't get any compilation errors, I would expect this
1234
5678
9101112
13141516
Change:
int ** Mat;
Mat=(int**)malloc(rows*columns*sizeof(int));
to:
int (*Mat)[columns];
Mat = malloc(rows * sizeof *Mat);
int ** Mat; declares Mat to be a pointer to a pointer to an int. But to make that work, you have to allocate space for a bunch of pointers (one for each row) and fill them in with pointers to space allocated for the rows. You did not do that.
You allocated space for rows * columns int, and you set Mat to point to that space. It seems like you want to use Mat as a pointer to a matrix (or, properly, to the first row of a matrix), not as a pointer to pointers. So declare it as int (*Mat)[columns];, which makes it a pointer to an array of four columns (specifically, it is pointing to the first such array, which is followed by others).
Your implementation is using a jagged array. That is, the Mat is an array of pointers where each pointer points to a row. The only part of your code that is wrong is the initialization. When you create the pointer for your Mat, the pointers to the rows come from whatever memory malloc gave you, and thus or not valid. You need to initialize the pointer for each row.
Mat=(int**)malloc(rows*sizeof(int*));
for (int i=0;i<rows;++i) {
Mat[i] = malloc(cols*sizeof(int));
}
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];
}
I created two 2D arrays (matrix) in C in two different ways.
I don't understand the difference between the way they're represented in the memory, and the reason why I can't refer to them in the same way:
scanf("%d", &intMatrix1[i][j]); //can't refer as &intMatrix1[(i * lines)+j])
scanf("%d", &intMatrix2[(i * lines)+j]); //can't refer as &intMatrix2[i][j])
What is the difference between the ways these two arrays are implemented and why do I have to refer to them differently?
How do I refer to an element in each of the arrays in the same way (?????? in my printMatrix function)?
int main()
{
int **intMatrix1;
int *intMatrix2;
int i, j, lines, columns;
lines = 3;
columns = 2;
/************************* intMatrix1 ****************************/
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix1[%d][%d]\t", i, j);
scanf("%d", &intMatrix1[i][j]);
}
}
/************************* intMatrix2 ****************************/
intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
for (i = 0; i < lines; ++i)
{
for (j = 0; j < columns; ++j)
{
printf("Type a number for intMatrix2[%d][%d]\t", i, j);
scanf("%d", &intMatrix2[(i * lines)+j]);
}
}
/************** printing intMatrix1 & intMatrix2 ****************/
printf("intMatrix1:\n\n");
printMatrix(*intMatrix1, lines, columns);
printf("intMatrix2:\n\n");
printMatrix(intMatrix2, lines, columns);
}
/************************* printMatrix ****************************/
void printMatrix(int *ptArray, int h, int w)
{
int i, j;
printf("Printing matrix...\n\n\n");
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j)
printf("array[%d][%d] ==============> %d\n, i, j, ??????);
}
You are dereferencing the Matrix1 two times..
Matrix1[i][j] ;
It means that it is a 2D array or a double pointer declared like this.
int **Matrix1 ;
A double pointer could be thought of as array of pointers. Its each element is a pointer itself, so it is dereferenced once to reach at the pointer element, and dereferenced twice to access the data member of that member pointer or array. This statement as you you wrote is equivalent to this one..
Matrix1[i][j] ; //is ~ to
*( *(Matrix1 + i) + j) ;
For a single pointer like this.
int *Matrix2 ;
You can derefernce it only once, like this.
Matrix2[i] ; //is ~ to
*(Matrix2 + i) ;
This statement which you wrote..
Matrix2[(i * lines)+j] ;
|-----------|
This portion evaluates to a single number, so it derefenced one time.
(i * lines) + j ;
As for your printmatrix() function, the ptArray passed to it is a single pointer. So you cannot dereference it twice.
Perhaps you can get better understanding of static and dynamic 2D arrays from my answer here.
2D-array as argument to function
Both matrices are sequences of bytes in memory. However, the difference between them is how you're defining the memory interface to represent a matrix. In one case you're just defining a memory segment with a number of elements equal to the elements in the matrix, and in the other case you're specifically allocating memory to represent each specific line.
The following case is more expensive computationally, because you're invoking malloc() a greater number of times:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
However, it brings the advantage that you get to refer to matrix elements in a clearer fashion:
intMatrix1[i][j];
If you just allocate one sequence of elements equal to the number of elements in the matrix, you have to take in account line/column index calculations to refer to the right matrix elements in memory.
To attempt to increase the degree of uniformity in the code, may I suggest a function that receives the matrix line reference and matrix column-count and prints a line?
void PrintLine(int *ptrLine, int lineLen) {
unsigned int i;
for(i = 0; i < lineLen; i++)
printf("%d ", ptrLine[i]);
printf("\n");
}
And then, for each matrix type, you would just do:
// Case 1
for(i = 0; i < lines; i++)
PrintLine(intMatrix1[i], columns);
// Case 2
for(i = 0; i < lines; i++) {
PrintLine(intMatrix2 + i*columns, columns);
}
In C, the array access operator [] is really just a cleaner way of performing pointer arithmetic. For a one-dimensional array of elements of type type_s, arr[i] is equivalent to *(arr + (i * sizeof(type_s))). To dissect that expression:
arr will be the base address, the lowest memory address where this array is stored
i is the zero-indexed position of the element in the array
sizeof returns the number of chars (which is generally the same as the number of bytes, but it's not mandated by the C spec) that an element in arr takes up in memory. The compiler will determine the size of the element and take care of performing this math for you.
As a side note, this syntax has the side effect of arr[i] being equivalent to i[arr], although it's universally accepted to put the index in brackets.
So with all of that said, let's look at the differences between your two declarations:
intMatrix1[i][j] is equivalent to *(*(intMatrix1 + i * sizeof(int)) + j * sizeof(int)). So, there are two dereference operators in that expression, meaning that intMatrix is an array of arrays (it contains pointers to pointers).
On the other hand, intMatrix2[(i * lines)+j] is equivalent to *(intMatrix2 + ((i * lines) + j) * sizeof(int)), which contains only one dereference operator. What you're doing here is defining a one-dimensional array that contains the same number of elements as the original two-dimensional array. If your data can be best represented by a matrix, then I recommend you use the first version: intMatrix1[i][j].
The difference is that the first array:
intMatrix1 = (int **)malloc(lines * sizeof(int *));
Creates an array of pointers intMatrix1. Each of those pointers points to an int array (which you malloc here).
for (i = 0; i < lines; ++i)
intMatrix1[i] = (int *)malloc(columns * sizeof(int));
That's why you need the 2 stars (dereference to the pointer array, then to the int array) in the declaration and the double brackets to access single elements:
int **intMatrix1;
int i = intMatrix[row][column];
int i = *(*(intmatrix + row) + column);
For the second matrix, you create just an int array of size column * rows.
int *intMatrix2 = (int *)malloc(lines * columns * sizeof(int));
int i = intMatrix[row + column];
int i = *(intMatrix + row + column);
To print the 2 arrays you will have to use different print functions, because the internal structure of the 2 matrix is different, but you already know the different methods to access both arrays.
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];
}