populating array without calloc and malloc in c? - c

I have code that looks like
int main(int argc, char *argv[]){
char ***matrix;
matrix = calloc(2, sizeof(char **));
for (int i=0; i<2; i++){
matrix[i] = calloc(ROWS+2, sizeof(char*));
for (int j=0; j<COLS; j++){
matrix[i][j] = malloc(COLS+2);
memset(matrix[i][j], (int)DEFAULT, COLS+2);
}
}
Is there a way to do a similar kind of thing without the use of malloc and calloc? For example, in the case of 1d array I know you can do something like this
unsigned char malloc_data[MAX_SIZE];
size_t malloc_used; /* automatically initialized to zero */
void *stack_malloc(size_t size) {
void *p = &malloc_data[malloc_used];
if(size + malloc_used > MAX_SIZE) return 0; /* out of memory */
malloc_used += size;
return p;
}
OR something like this
static char *allocp = allocbuf[0];
if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */
and
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
I want to try to use stack variables and temps instead of dynamic memory allocated ways. However, when I try to think about how to apply these types of ways to my three dimensional sense, my head starts spinning. Please help clarify things to me

Assuming you want to keep the triple pointer usage, the storage can be allocated on the stack and initialized like this:
char ***matrix;
char **mats_[2];
char *mat_rows_[2][ROWS+2];
char mat_cols_[2][ROWS+2][COLS+2];
matrix = &mats_[0];
for (int i = 0; i < 2; i++) {
matrix[i] = &mat_rows_[i][0];
for (int j = 0; j < ROWS+2; j++) {
matrix[i][j] = &mat_cols_[i][j][0];
memset(matrix[i][j], (int)DEFAULT, COLS+2);
}
}
You could also define matrix as an array[2] of char ** instead of a single char ***, which would allow you to eliminate the mats_ variable:
char **matrix[2];
char *mat_rows_[2][ROWS+2];
char mat_cols_[2][ROWS+2][COLS+2];
for (int i = 0; i < 2; i++) {
...
In the comments below, OP asked whether the memset was necessary. All the elements of mat_cols_[2][ROWS+2][COLS+2] need to be set to the same value DEFAULT. If DEFAULT can be replaced with 0, this is easy to do by defining mat_cols_ with an initializer with pretty much everything defaulting to 0:
char mat_cols_[2][ROWS+2][COLS+2] = { 0 };
If DEFAULT cannot be replaced with 0, the only way to do it would be for the initializer to supply values for all the elements explicitly, which has a maintainability problem since the dimensions are defined in terms of the macros ROWS and COLS. The GNU C Compiler (GCC) has an extension to the C language designated initializers that allows a range of array elements to be initialized to the same value. That could be used as follows:
char mat_cols_[2][ROWS+2][COLS+2] =
{[0 ... 1] =
{[0 ... ROWS+2-1] =
{[0 ... COLS+2-1] = DEFAULT}
}
};

Related

How to declare an 2d array pointer of fixed size elements

I wanted to declare an 2d array in a header file such as;
char ar[][4];
So the array has no decided number of elements known before the program is run (But the length of each element is known). But I can't use malloc here because ar is declared this way.
So I tried this;
char* ar[4];
But this only gives an array of 4 pointers (not my goal).
Do I have to use char** or there is another workaround that I can use to declare the length of each element ?
Declaring something like
char ar[][4];
is typically met with a compiler error such as
'ar': unknown size
because fixed arrays must have a defined size at compile time.
For an array to have its size defined during run-time you must use dynamic allocation.
Here's a very simple example.
char** alloc2dArray(const int rows, const int rowlen) {
// allocate the array of rows.
size_t size = rows * sizeof(char*);
char** pptr = (char**)malloc(size);
// allocate the rows.
for (int i = 0; i < rows; i++) {
pptr[i] = (char*)malloc(rowlen);
}
return pptr;
}
void free2dArray(char** pptr, const int rows) {
// free the rows
for (int i = 0; i < rows; i++)
free(pptr[i]);
// free array of rows
free(pptr);
}
And note with pointer-to-pointer you get square bracket sugar
const int rows = 7;
const int rowlen = 4;
char** arr = alloc2dArray(rows, rowlen);
char c = '#';
for (int i = 0; i < rows; i++) {
int j = 0;
for (; j < rowlen; j++) {
arr[i][j] = c++;
}
}
free2dArray(arr, rows);

Erros in dynamically allocated array in C

I am trying to dynamically allocate a 2D array, put some values, and print output. However it seems that I am making mistake in getting input to program in atoi() function.
Basically when we assign a static 2D array, we declare it as say int a [3][3]. So 3*3 units if int, that much memory gets allocated. Is same thing holds for allocating dynamic array as well?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(int arg,char* argv)
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
int (*arr)[col] = malloc(sizeof (*arr)*rows);
int *ptr = &(arr[0][0]);
int ct=1;
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
arr[i][j]=ct;
ct++;
}
}
printf("printing array \n");
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
free(arr);
return (0);
}
Program crashes in runtime. Can someone comment?
Try to change the third line to:
int main(int arg,char **argv)
The common method to use dynamic matrices is to use a pointer to pointer to something, and then allocate both "dimensions" dynamically:
int **arr = malloc(sizeof(*arr) * rows);
for (int i = 0; i < rows; ++i)
arr[i] = malloc(sizeof(**arr) * col);
Remember that to free the matrix, you have to free all "rows" in a loop first.
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
You are defining rows and col twice.... that would never work!
With traditional C, you can only have the array[][] structure for multiple dimension arrays work with compile time constant values. Otherwise, the pointer arithmetic is not correct.
For dynamically sized multi dimensional arrays (those where rows and cols are determined at runtime), you need to do additional pointer arithmetic of this type:
int *a;
int rows=3;
int cols=4;
a = malloc(rows * cols * sizeof(int));
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
a[i*rows + j] = 1;
free(a);
Alternatively, you can use double indirection and have an array of pointers each pointing to a one dimensional array.
If you are using GCC or any C99 compiler, dynamic calculation of multiple dimension arrays is simplified by using variable length arrays:
// This is your code -- simplified
#include <stdio.h>
int main(int argc, const char * argv[])
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
// you can have a rough test of sanity by comparing rows * col * sizeof(int) < SIZE_MAX
int arr[rows][col]; // note the dynamic sizing of arr here
int ct=1;
for (int i=0;i<rows;i++)
for(int j=0;j<col;j++)
arr[i][j]=ct++;
printf("printing array \n");
for (int i=0;i<rows;i++)
{
for(int j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
return 0;
} // arr automatically freed off the stack
With a variable length array ("VLA"), dynamic multiple dimension arrays in C become far easier.
Compare:
void f1(int m, int n)
{
// dynamically declare an array of floats n by m size and fill with 1.0
float *a;
a = malloc(m * n * sizeof(float));
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i*n + j] = 1.0;
free(a);
}
With VLA you can write to do the same:
void f2(int m, int n)
{
// Use VLA to dynamically declare an array of floats n by m size and fill with 1.0
float a[m][n];
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
a[i][j] = 1.0;
}
Be aware that unlike malloc / free VLA's handling of requesting a size larger than what is available on the stack is not as easily detected as using malloc and testing for a NULL pointer. VLA's are essentially automatic variables and have similar ease and restrictions.
VLA's are better used for smaller data structures that would be on the stack anyway. Use the more robust malloc / free with appropriate detection of failure for larger data structures.
If you are not using a fairly recent vintage C compiler that supports C99 -- time to get one.

C Malloc Multidimensional Char Array

I would like to dynamically allocate (malloc) a multidimensional character array in C. The array would have the following format:
char *array[3][2] = {
{"one","two"},
{"three","four"},
{"five","six"}
};
Before the array would be created, I would already know the number of rows and the lengths of all of the characters arrays in the multidimensional array.
How would I malloc such a character array?
Thanks in advance!
This is one way to allocate a two dimensional array of char *.
Afterwards, you can assign the contents like a[1][2] = "foo";
Note that the elements of the array are initialized to (char *)0.
#include <stdio.h>
#include <stdlib.h>
char ***alloc_array(int x, int y) {
char ***a = calloc(x, sizeof(char **));
for(int i = 0; i != x; i++) {
a[i] = calloc(y, sizeof(char *));
}
return a;
}
int main() {
char ***a = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
[Charlies-MacBook-Pro:~] crb% cc xx.c
[Charlies-MacBook-Pro:~] crb% a.out
foo
First of all, arrays are typically stored in Row Major form, so in reality you have a vector six elements long, each entry is a char * ptr. That is, the elements labelled by row, column are similar to:
char *r1c1, *r1c2, *r2c1, *r2c2, *r3c1, *r3c1;
Thus, do a SIMPLE malloc of:
char *matrix = malloc(3*2*sizeof(char *));
Then set the elements as:
matrix[0] = "one";
matrix[1] = "two";
matrix[2] = "three";
matrix[3] = "four";
matrix[4] = "five";
matrix[5] = "six";
Finally, to test this write a nested loop as:
for (int r=0; r<3; r++)
{
for (int c=0; c<2; c++);
{
printf("%s\n",matrix[r][c]);
}
}
Note, how a matrix is treated first as a vector then as a matrix. C doesn't care!!
char *array[3][2] is nothing but a two dimensional array of pointers. Hence you need the storage space of 3*2*sizeof(char *) to store the pointers.
As you mentioned, the pointers are actually pointing to zero-terminated strings and you may like the strings to be malloc'ed as well. Assuming the total length of all the strings to be N (including zero-termination), the storage space needed is (3*2*sizeof(char *) + N).
Allocate memory for the above mentioned size and the copy the strings yourselves as below.
In the following code, we assume that the number of columns (2) is a constant
char *(*dst)[2] = (char *(*)[2]) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i][j] = s;
s += strlen(s)+1;
}
}
NOTE: In the above code, 'dst' is a pointer that points to the first row of the 2D array of char *.
If the number of columns is not constant, the syntax changes a bit, but the storage size is the same.
char **dst = (char **) malloc(3*2*sizeof(char *) + N);
char * s = ((char *) dst) + (3*2*sizeof(char *));
for (i = 0; i < 3; i++)
{
for (j = 0; j < 2; j++)
{
strcpy(s, src[i][j]);
dst[i*2 + j] = s; /* 2 is the number of columns */
s += strlen(s)+1;
}
}
NOTE: Here 'dst' is a pointer that points to the first element of 1D array of char * and the 2D indexing is done manually.
The above examples assume that the string lengths will not change after allocation. If the strings can change at any point in time after allocation, then it is better to allocate for each string separately.
Keep it simple, Sheldon. The answer you've selected uses a char ***, which is not even close to the equivalent of a char *[2][3]. The difference is in the number of allocations... An array only ever requires one.
For example, here's how I'd retro-fit the answer you selected. Notice how much simpler it is?
#include <stdio.h>
#include <stdlib.h>
void *alloc_array(size_t x, size_t y) {
char *(*a)[y] = calloc(x, sizeof *a);
return a;
}
int main() {
char *(*a)[2] = alloc_array(3, 2);
a[2][1] = "foo";
printf("%s\n", a[2][1]);
}
In case you arrive in this page, wanting to create an array like int myarray[n][M] (which is slighly different from the question since they want an array of string), where M is fixed and n can vary (for example if you want an array of coordinates...), then you can just do:
int (*p)[M] = malloc(n*sizeof *p);
and then use p[i][j] as before. Then, you will get sizeof p[i] = M*sizeof(int):
#include <stdio.h>
#include <stdlib.h>
#define M 6
int main(int argc, char *argv[])
{
int n = 4;
int (*p)[M] = malloc(n*sizeof *p);
printf("Size of int: %lu\n", sizeof(int));
printf("n = %d, M = %d\n", n, M);
printf("Size of p: %lu (=8 because pointer in 64bits = 8 bytes)\n", sizeof p);
printf("Size of *p: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof *p);
printf("Size of p[0]: %lu (=M*sizeof(int) because each case is an array of length M)\n", sizeof p[0]);
// Assign
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
(p[i])[j] = i*10+j;
}
}
// Display
for (int i=0; i<n; i++) {
for (int j=0; j<M; j++) {
printf("%2d; ", (p[i])[j]);
}
printf("\n");
}
return 0;
}
which gives:
Size of int: 4
n = 4, M = 6
Size of p: 8 (=8 because pointer in 64bits = 8 bytes)
Size of *p: 24 (=M*sizeof(int) because each case is an array of length M)
Size of p[0]: 24 (=M*sizeof(int) because each case is an array of length M)
0; 1; 2; 3; 4; 5;
10; 11; 12; 13; 14; 15;
20; 21; 22; 23; 24; 25;
30; 31; 32; 33; 34; 35;

How do we allocate a 2-D array using One malloc statement

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));

Passing variable sized multi-dimensional array by pointer in C

I am trying to pass a 2D array of variable size to a function to print it. I know how it's done when one has fixed sized arrays. But how does one do this with variable sized arrays? Here is some code that'll give you an idea what I am trying to do:
void print_grid(char (*g)[9], int size) // the array subscript (9 here) be variable
{
int i, j;
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
printf("%c ", g[i][j]);
printf("\n");
}
}
I'll call this function using the following code:
char a[3][3], b[9][9];
// assign a, b
print_grid(a, 3);
print_grid(b, 9);
Is there any way to do this without allocating any dynamic memory in print_grid()?
void print_grid(int rows, int cols, char g[][cols]) { ... }
void print_grid(char *g, int size)
{
int i, j;
for( i = 0; i < size; i++)
for( j = 0; j < size; j++)
{
printf("%c ", *(g + i*size + j));
printf("\n");
}
}
print_grid(a, 3);
When you pass an array in C it is always passed by reference, i.e. through a pointer. The type of this pointer is not pointer-to-array, but pointer-to-first-element. For example, the code generator will handle void f(char[][10]) as if it where void f(char*). The array dimensions are lost. The parser, however, will complain if it sees f declared twice so.
The motivation behind C was to have a powerful and portable assembler, not a new programming language. Multidimensional arrays are logical constructs that do not exist in the machine. Arrays are a way of thinking.
To pass the dimensions of arrays to functions C programmers traditionally use structs:
typedef struct array_tag {
int count;
char data[1]; /* actually data[count] */
} ARRAY;
typedef struct grid_tag {
int rows, columns;
char grid[1][1]; /* actually grid[rows][columns] */
} GRID;
void f(ARRAY* x)
{
int i;
for (i = 0; i < x->count; ++i) {
char c = x->data[i];
}
}
void g(GRID* x)
{
int i, j;
for (i = 0; i < x->rows; ++i)
for (j = 0; j < x->columns; ++j) {
char c = x->grid[i][j];
}
}
void h()
{
{
const int len = 100;
ARRAY* x = (ARRAY*) malloc(sizeof(ARRAY) + len * sizeof(char));
x->count = len;
f(x);
}
{
const int rows = 2, cols = 3;
GRID* x = (GRID*) malloc(sizeof(GRID) + rows * cols * sizeof(char));
x->rows = rows;
x->columns = cols;
g(x);
}
}
Yes, the malloc expression in this example allocates few bytes too much. Therefore the GNU-compiler supports arrays of zero length for a long time, which are not allowed in C90.
C99 has gone one step further with flexible arrays. From ISO/IEC 9899:1999, Section 6.7.2.1, paragraph 16: "As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member." In C99 the ARRAY and GRID types can be declared as:
typedef struct array_tag {
int count;
char data[]; /* actually data[count] */
} ARRAY;
typedef struct grid_tag {
int rows, columns;
char grid[][1]; /* actually grid[rows][columns] */
} GRID;
and you can
assert(1*sizeof(int) == sizeof(ARRAY));
assert(2*sizeof(int) == sizeof(GRID));
Many people think C arrays are quirky. But they're also an elegant solution which allows the declaration of indefinitely complex arrays. It is known as the "K&R array equation". A good explanation can be found here.
Hope this helps.
This one does it, assuming a squared grid:
void print_grid(void* g, int size)
{
char* my = (char*) g;
int i, j;
for (i=0; i<size; i++)
{
for (j=0; j<size; j++)
printf("%c ", my[i+j]);
printf("\n");
}
}
If you want to use non-squared grids, replace size with a rows and columns parameter and adjust counting: i<rows and j<columns.

Resources