typedef struct {
int num_rows;
int num_cols;
int** data;
} BinaryMatrix;
BinaryMatrix *ConstructBinaryMatrix(int num_rows, int num_cols) {
BinaryMatrix matrix = {
.num_rows = num_rows,
.num_cols = num_cols,
.data = (int **) malloc((num_rows) * sizeof(int *)),
};
int i;
for (i = 0; i < num_cols; i++) {
matrix.data[i] = (int *) malloc(num_cols * sizeof(int));
}
return &matrix;
}
Is this the correct way to define a BinaryMatrix, and how to initialize it?
Thanks for your help.
I got the following error.
BinaryMatrix* M;
M = ConstructBinaryMatrix(2, 2);
printf("%d:%d", M->num_rows, M->num_cols);
The output is: 4198012:0
You are returning a pointer to local data, which is bad form and doesn't work.
You should probably call malloc to allocate space for a BinaryMatrix structure, something like this:
BinaryMatrix *ConstructBinaryMatrix(int num_rows, int num_cols) {
BinaryMatrix *matrix = malloc(sizeof(BinaryMatrix));
matrix->num_rows = num_rows;
matrix->num_cols = num_cols,
matrix->data = malloc(num_rows * sizeof(int *));
int i;
for (i = 0; i < num_rows; i++) {
matrix->data[i] = malloc(num_cols * sizeof(int));
}
return matrix;
}
(Also I have fixed the loop bounds, as M.M. pointed out.)
i < num_cols should be i < num_rows.
Currently your code returns the address of a local variable. Local variables are destroyed when the function returns, so you in fact return a dangling pointer, not a good idea.
Instead you should return a copy of the local variable. Remove the * from the function prototype and from declaration of M, and remove the & from the return statement.
Unless its very large I would use:
#define M 3
#define N 3
int matrix[M][N]={{0,0,0},{0,0,0},{0,0,0}};
/* above possibly static */
Simples !
If the matrix was large simply use for loops to initialize.
Related
I have a c program in which I want to initialize a 2 dimensional array.
So I made this function :
void initLayer(int **layer, int *dimensions) {
printf("initLayer\n");
layer = malloc(sizeof(int*) * dimensions[0]);
for (int i = 0; i < dimensions[0]; i++) {
layer[i] = malloc(sizeof(int) * dimensions[1]);
}
}
When I use this function there is no problem, but when I try to read the 2D array later I always get a segmentation fault.
I think it may be because the initialization made in the function are not saved when its finished.
Do you know how I could correct my function ? Thank you in advance.
To passing pointer to function you need one more pointer.
int **matrix; is an array of arrays, so to fill it you need to pass it as a pointer, which is int ***layer. but it is weird.
also for changing data by pointer you need to add a star * before it. *layer = ...
#include <stdlib.h>
void initLayer(int ***layer, int *dimensions)
{
*layer = malloc(sizeof(int *) * dimensions[0]);
for (int i = 0; i < dimensions[0]; i++)
{
*(*layer + i) = malloc(sizeof(int) * dimensions[1]);
}
}
int main()
{
int **matrix;
int dimensions[2] = { 4, 6 };
initLayer(&matrix, dimensions);
// then do whatever you want
for (int i = 0; i < dimensions[0]; i++)
{
for (int j = 0; j < dimensions[1]; j++)
{
matrix[i][j] = i * j;
}
}
}
as for me, better to use typedef to make code more readable:
#include <stdlib.h>
typedef int * Array;
typedef int ** Matrix;
void initLayer(Matrix *layer, Array dimensions)
{
*layer = malloc(sizeof(Array) * dimensions[0]);
for (int i = 0; i < dimensions[0]; i++)
{
(*layer)[i] = malloc(sizeof(int) * dimensions[1]);
}
}
int main()
{
Matrix matrix;
int dimensions[2] = { 4, 6 };
initLayer(&matrix, dimensions);
// then do whatever you want
for (int i = 0; i < dimensions[0]; i++)
{
for (int j = 0; j < dimensions[1]; j++)
{
matrix[i][j] = i * j;
}
}
}
When you call the function, the int **layer pointer is copied. So, when you do layer = malloc(...) what actually happens is the function sets its local copy to the malloc result. What you want is to mutate the variable which you called the function with. You can do this by taking a int ***layer and passing in &layer when calling initLayer. Note that you must then use *layer instead of layer in your code.
You have two approaches here:
to pass a reference to the double pointer (***int in this case)
or to return the allocated pointer as the result of your function:
in the first case:
void initLayer(int ***layer, int *dimensions) {
printf("initLayer\n");
*layer = malloc(sizeof(int*) * dimensions[0]);
for (int i = 0; i < dimensions[0]; i++) {
layer[i] = malloc(sizeof(int) * dimensions[1]);
}
}
you pass a reference to a pointer, instead of passing the (uninitialized) pointer. Remember, in C, all parameters are passed by value. In this case, you can call your function as:
...
int**vector;
...
initLayer(&vector, dims); /* you pass the address of your double pointer */
In the second case:
int** initLayer(int *dimensions) {
printf("initLayer\n");
int **layer = malloc(sizeof(int*) * dimensions[0]);
for (int i = 0; i < dimensions[0]; i++) {
layer[i] = malloc(sizeof(int) * dimensions[1]);
}
return layer;
}
in this case, you call it as:
...
int**vector;
...
vector = initLayer(dims); /* you receive your double pointer as a return value */
I've got a problem.
I need to write a function which will allocate any 2D array with malloc() but I'm lost and have no idea what might be wrong.
Here is what I wrote so far:
void matrix_ini(int **arr, int SIZE_X, int SIZE_Y);
int main() {
int **arr;
matrix_ini(arr, 2, 3);
return 0;
}
void matrix_ini(int **arr, int SIZE_X, int SIZE_Y) {
srand(time(NULL));
arr = malloc(SIZE_X * sizeof *arr);
for (int i = 0; i < SIZE_X; i++) {
arr[i] = malloc(SIZE_Y * sizeof arr);
}
//initializing array with some numbers:
for (int i = 0; i < SIZE_X; i++) {
for (int j = 0; j < SIZE_Y; j++) {
arr[i][j] = rand()%10;
}
}
}
What exactly am I doing wrong?
Please be gentle, I just started learning. Any tips are welcome.
Problem #1:
This:
arr = malloc(SIZE_X * sizeof(*arr));
Is equivalent to this:
arr = malloc(SIZE_X * sizeof(int*));
Which is OK for your purpose.
But this:
arr[i] = malloc(SIZE_Y * sizeof(arr));
Is equivalent to this:
arr[i] = malloc(SIZE_Y * sizeof(int**));
Which is not OK for your purpose.
So change it to this:
arr[i] = malloc(SIZE_Y * sizeof(int));
Problem #2:
If you want a function to change the value of a variable that you call it with, then you have to call it with the address of that variable. Otherwise, it can change the value of that variable only locally (i.e., within the scope of the function). This pretty much forces you to change the entire prototype, implementation and usage of function matrix_init:
void matrix_init(int*** arr, int SIZE_X, int SIZE_Y)
{
int** temp_arr;
temp_arr = malloc(SIZE_X * sizeof(int*));
for (int i = 0; i < SIZE_X; i++)
{
temp_arr[i] = malloc(SIZE_Y * sizeof(int));
for (int j = 0; j < SIZE_Y; j++)
{
temp_arr[i][j] = rand()%10;
}
}
*arr = temp_arr;
}
Then, in function main, you should call matrix_init(&arr,2,3).
Problem #3:
You should make sure that you release any piece of memory which is dynamically allocated during runtime, at some later point in the execution of your program. For example:
void matrix_free(int** arr, int SIZE_X)
{
for (int i = 0; i < SIZE_X; i++)
{
free(arr[i]);
}
free(arr);
}
Then, in function main, you should call matrix_free(arr,2).
I have been asked in an interview how do i allocate a 2-D array and below was my solution to it.
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
I thought I had done a good job but then he asked me to do it using one malloc() statement not two. I don't have any idea how to achieve it.
Can anyone suggest me some idea to do it in single malloc()?
Just compute the total amount of memory needed for both nrows row-pointers, and the actual data, add it all up, and do a single call:
int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));
If you think this looks too complex, you can split it up and make it a bit self-documenting by naming the different terms of the size expression:
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
You then need to go through and initialize the row pointers so that each row's pointer points at the first element for that particular row:
size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
array[i] = data + i * ncolumns;
Note that the resulting structure is subtly different from what you get if you do e.g. int array[nrows][ncolumns], because we have explicit row pointers, meaning that for an array allocated like this, there's no real requirement that all rows have the same number of columns.
It also means that an access like array[2][3] does something distinct from a similar-looking access into an actual 2d array. In this case, the innermost access happens first, and array[2] reads out a pointer from the 3rd element in array. That pointer is then treatet as the base of a (column) array, into which we index to get the fourth element.
In contrast, for something like
int array2[4][3];
which is a "packed" proper 2d array taking up just 12 integers' worth of space, an access like array[3][2] simply breaks down to adding an offset to the base address to get at the element.
int **array = malloc (nrows * sizeof(int *) + (nrows * (ncolumns * sizeof(int)));
This works because in C, arrays are just all the elements one after another as a bunch of bytes. There is no metadata or anything. malloc() does not know whether it is allocating for use as chars, ints or lines in an array.
Then, you have to initialize:
int *offs = &array[nrows]; /* same as int *offs = array + nrows; */
for (i = 0; i < nrows; i++, offs += ncolumns) {
array[i] = offs;
}
Here's another approach.
If you know the number of columns at compile time, you can do something like this:
#define COLS ... // integer value > 0
...
size_t rows;
int (*arr)[COLS];
... // get number of rows
arr = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < COLS; j++)
arr[i][j] = ...;
}
If you're working in C99, you can use a pointer to a VLA:
size_t rows, cols;
... // get rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
arr[i][j] = ...;
}
How do we allocate a 2-D array using One malloc statement (?)
No answers, so far, allocate memory for a true 2D array.
int **array is a pointer to pointer to int. array is not a pointer to a 2D array.
int a[2][3] is an example of a true 2D array or array 2 of array 3 of int
To allocate memory for a true 2D array, with C99, use malloc() and save to a pointer to a variable-length array (VLA)
// Simply allocate and initialize in one line of code
int (*c)[nrows][ncolumns] = malloc(sizeof *c);
if (c == NULL) {
fprintf(stderr, "out of memory\n");
return;
}
// Use c
(*c)[1][2] = rand();
...
free(c);
Without VLA support, if the dimensions are constants, code can use
#define NROW 4
#define NCOL 5
int (*d)[NROW][NCOL] = malloc(sizeof *d);
You should be able to do this with (bit ugly with all the casting though):
int** array;
size_t pitch, ptrs, i;
char* base;
pitch = rows * sizeof(int);
ptrs = sizeof(int*) * rows;
array = (int**)malloc((columns * pitch) + ptrs);
base = (char*)array + ptrs;
for(i = 0; i < rows; i++)
{
array[i] = (int*)(base + (pitch * i));
}
I'm not a fan of this "array of pointers to array" to solve the multi dimension array paradigm. Always favored a single dimension array, at access the element with array[ row * cols + col]? No problems encapsulating everything in a class, and implementing a 'at' method.
If you insist on accessing the members of the array with this notation: Matrix[i][j], you can do a little C++ magic. #John solution tries to do it this way, but he requires the number of column to be known at compile time. With some C++ and overriding the operator[], you can get this completely:
class Row
{
private:
int* _p;
public:
Row( int* p ) { _p = p; }
int& operator[](int col) { return _p[col]; }
};
class Matrix
{
private:
int* _p;
int _cols;
public:
Matrix( int rows, int cols ) { _cols=cols; _p = (int*)malloc(rows*cols ); }
Row operator[](int row) { return _p + row*_cols; }
};
So now, you can use the Matrix object, for example to create a multiplication table:
Matrix mtrx(rows, cols);
for( i=0; i<rows; ++i ) {
for( j=0; j<rows; ++j ) {
mtrx[i][j] = i*j;
}
}
You should now that the optimizer is doing the right thing and there is no call function or any other kind of overhead. No constructor is called. As long as you don't move the Matrix between function, even the _cols variable isn't created. The statement mtrx[i][j] basically does mtrx[i*cols+j].
It can be done as follows:
#define NUM_ROWS 10
#define NUM_COLS 10
int main(int argc, char **argv)
{
char (*p)[NUM_COLS] = NULL;
p = malloc(NUM_ROWS * NUM_COLS);
memset(p, 81, NUM_ROWS * NUM_COLS);
p[2][3] = 'a';
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLS; j++) {
printf("%c\t", p[i][j]);
}
printf("\n");
}
} // end of main
You can allocate (row*column) * sizeof(int) bytes of memory using malloc.
Here is a code snippet to demonstrate.
int row = 3, col = 4;
int *arr = (int *)malloc(row * col * sizeof(int));
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*col + j) = ++count; //row major memory layout
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", *(arr + i*col + j));
I am new to C and during my learning I want to return a two dimensional array from a function, so that I can use it in my main program. Can anyone explain me the same with example. Thanks in advance.
It depends how it is implemented. You can either work with just a one-dimensional array where you know the length of each (row) and the next row begins immediately after the previous one. OR, you can have an array of pointers to arrays. The extra cost though is you need to de-reference two pointers to get to one element of data.
// 2D array of data, with just one array
char* get_2d_ex1(int rows, int cols) {
int r, c, idx;
char* p = malloc(rows*cols);
for (r=0; r<rows; r++) {
for (c=0; c<cols; c++) {
idx = r*cols + c; // this is key
p[idx] = c; // put the col# in its place, for example.
}
}
return p;
}
Declare your function as returning a pointer to a pointer. If we use int as an example:
int **samplefunction() {
int** retval = new int*[100];
for (int i = 1; i < 100; i++) {
retval[i] = new int[100];
}
// do stuff here to retval[i][j]
return retval;
}
Here's an example of how you might create, manipulate and free a "2d array":
#include <stdlib.h>
#define ROWS 5
#define COLS 10
int **create_2d_array(size_t rows, size_t cols)
{
size_t i;
int **array = (int**)malloc(rows * sizeof(int*));
for (i = 0; i < rows; i++)
array[i] = (int*)malloc(cols * sizeof(int));
return array;
}
void free_2d_array(int **array, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
free(array[i]);
free(array);
}
int main(void)
{
int **array2d = create_2d_array(ROWS, COLS);
/* ... */
array2d[3][4] = 5;
/* ... */
free_2d_array(array2d, ROWS, COLS);
return 0;
}
To create a "2d array"/matrix, all you have to do is create a dynamic array of pointers (in this case int*) of the size of the rows/width:
int **array = (int**)malloc(rows * sizeof(int*));
Then you set each of those pointers to point to a dynamic array of int of the size of the columns/height:
array[i] = (int*)malloc(cols * sizeof(int));
Note that the casts on malloc aren't required, it's just a habit I have.
I don't truly understand some basic things in C like dynamically allocating array of arrays.
I know you can do:
int **m;
in order to declare a 2 dimensional array (which subsequently would be allocated using some *alloc function). Also it can be "easily" accessed by doing *(*(m + line) + column). But how should I assign a value to an element from that array? Using gcc the following statement m[line][column] = 12; fails with a segmentation fault.
Any article/docs will be appreciated. :-)
The m[line][column] = 12 syntax is ok (provided line and column are in range).
However, you didn't write the code you use to allocate it, so it's hard to get whether it is wrong or right. It should be something along the lines of
m = (int**)malloc(nlines * sizeof(int*));
for(i = 0; i < nlines; i++)
m[i] = (int*)malloc(ncolumns * sizeof(int));
Some side-notes:
This way, you can allocate each line with a different length (eg. a triangular array)
You can realloc() or free() an individual line later while using the array
You must free() every line, when you free() the entire array
Your syntax m[line][colummn] is correct. But in order to use a 2D array in C, you must allocate memory for it. For instance this code will allocated memory for a table of given line and column.
int** AllocateArray(int line, int column) {
int** pArray = (int**)malloc(line*sizeof(int*));
for ( int i = 0; i < line; i++ ) {
pArray[i] = (int*)malloc(column*sizeof(int));
}
return pArray;
}
Note, I left out the error checks for malloc for brevity. A real solution should include them.
It's not a 2d array - it's an array of arrays - thus it needs the multiple allocations.
Here's a modified version of quinmars' solution which only allocates a single block of memory and can be used with generic values by courtesy of void *:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void ** array2d(size_t rows, size_t cols, size_t value_size)
{
size_t index_size = sizeof(void *) * rows;
size_t store_size = value_size * rows * cols;
char * a = malloc(index_size + store_size);
if(!a) return NULL;
memset(a + index_size, 0, store_size);
for(size_t i = 0; i < rows; ++i)
((void **)a)[i] = a + index_size + i * cols * value_size;
return (void **)a;
}
int printf(const char *, ...);
int main()
{
int ** a = (int **)array2d(5, 5, sizeof(int));
assert(a);
a[4][3] = 42;
printf("%i\n", a[4][3]);
free(a);
return 0;
}
I'm not sure if it's really safe to cast void ** to int ** (I think the standard allows for conversions to take place when converting to/from void * ?), but it works in gcc. To be on the safe side, you should replace every occurence of void * with int * ...
The following macros implement a type-safe version of the previous algorithm:
#define alloc_array2d(TYPE, ROWS, COLS) \
calloc(sizeof(TYPE *) * ROWS + sizeof(TYPE) * ROWS * COLS, 1)
#define init_array2d(ARRAY, TYPE, ROWS, COLS) \
do { for(int i = 0; i < ROWS; ++i) \
ARRAY[i] = (TYPE *)(((char *)ARRAY) + sizeof(TYPE *) * ROWS + \
i * COLS * sizeof(TYPE)); } while(0)
Use them like this:
int ** a = alloc_array2d(int, 5, 5);
init_array2d(a, int, 5, 5);
a[4][3] = 42;
Although I agree with the other answers, it is in most cases better to allocate the whole array at once, because malloc is pretty slow.
int **
array_new(size_t rows, size_t cols)
{
int **array2d, **end, **cur;
int *array;
cur = array2d = malloc(rows * sizeof(int *));
if (!array2d)
return NULL;
array = malloc(rows * cols * sizeof(int));
if (!array)
{
free(array2d);
return NULL;
}
end = array2d + rows;
while (cur != end)
{
*cur = array;
array += cols;
cur++;
}
return array2d;
}
To free the array simply do:
free(*array); free(array);
Note: this solution only works if you don't want to change the order of the rows, because you could then lose the address of the first element, which you need to free the array later.
Humm. How about old fashion smoke and mirrors as an option?
#define ROWS 5
#define COLS 13
#define X(R, C) *(p + ((R) * ROWS) + (C))
int main(void)
{
int *p = (int *) malloc (ROWS * COLS * sizeof(int));
if (p != NULL)
{
size_t r;
size_t c;
for (r = 0; r < ROWS; r++)
{
for (c = 0; c < COLS; c++)
{
X(r,c) = r * c; /* put some silly value in that position */
}
}
/* Then show the contents of the array */
for (r = 0; r < ROWS; r++)
{
printf("%d ", r); /* Show the row number */
for (c = 0; c < COLS; c++)
{
printf("%d", X(r,c));
}
printf("\n");
}
free(p);
}
else
{
/* issue some silly error message */
}
return 0;
}
Using malloc(3) for allocate the first array and putting in there pointers created by malloc(3) should work with array[r][c] because it should be equivalent to *(*(array + r) + c), it is in the C standard.