I want to allot memory dynamically for a 2D array.
Is there any difference between these two ?
1)
array = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
array[i] = (int *) malloc(size * sizeof(int));
}
2)
array = (int**)malloc(size *size* sizeof(int));
If yes, what is better to use and why ?
In the first case
array = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
array[i] = (int *) malloc(size * sizeof(int));
}
you are allocating size extents of the size equal to size * sizeof( int ) That is you are allocating size one-dimensional arrays. Accordingly you are allocating size pointers that point to first elements of these one-dimensional arrays.
In the second case expression
(int**)malloc(size *size* sizeof(int))
means allocation of an extent of size * size of objects of type int and the returned pointer is interpretated as int **. So this expression has no sense independing on what is placed in the left side of the assignment. take into account that the size of pointer can be greater than the size of int.
You could write instead
int ( *array )[size] = ( int (*)[size] )malloc(size *size* sizeof(int));
In this case you are indeed allocating a two dimensional array provided that size is a constant expression.
Those two solutions are very different. The first will give you a vector of pointers to vectors. The second will give you a vector of the requested size. It all depends on your use case. Which do you want?
When it comes to releasing the memory, the first can only be freed by calling free for each pointer in the vector and then a final free on the vector itself. The second can be freed with a single call. Don't have that be your deciding reason to use one or the other. It all depends on your use case.
What is the type of the object you want to allocate? Is it an int **, an int *[] or an int[][]?
I want to allot memory dynamically for a 2 dimensional array.
Then just do
int (*arr)[size] = malloc(size * sizeof *arr);
Is there any difference between these two ?
Yes, they are wrong because of different errors. The first attempt does not allocate a 2D array, it allocates an array of pointers and then a bunch of arrays of ints. Hence the result will not necessarily be contiguous in memory (and anyway, a pointer-to-pointer is not the same thing as a two-dimensional array.)
The second piece of code does allocate a contiguous block of memory, but then you are treating it as if it was a pointer-to-pointer, which is still not the same thing.
Oh, and actually, both snippets have a common error: the act of casting the return value of malloc().
Related
Three questions in 1.
If I have a 2-D array -
int array_name[num_rows][num_columns]
So it consists of num_rows arrays -each of which is an array of size = num_columns. Its equivalent representation using an array of pointers is-
int* array_name[num_rows]
-so the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right? I saw some texts telling
int* array_name[num_columns]
will the indices not get switched in this case ?
For a ID array I specify size dynamically as-
int *p;
p = (int*) malloc (size * sizeof(int))
For 2 D arrays do I specify the size of entire 2-D array or of one 1-D array in malloc -
int*p [row_count];
p = (int*) malloc (row_count * column_count * sizeof(int))
or
p = (int*) malloc (column_count * sizeof(int))
I think it should be the second since p is a pointer to a 1-D array and p+1 is a pointer to a 1-D array etc. Please clarify.
For ques 2 - what if p was defined as -
int **p; rather than
int * p[row_count]
How will the malloc be used then? I think it should be -
p = (int*) malloc (row_count * column_count * sizeof(int))
Please correct, confirm, improve.
Declaring :
int *array_name[num_rows];
or :
int *array_name[num_columns];
is the same thing. Only the name changes, but your variable is still referring to rows because C is a row major so you should name it row.
Here is how to allocate a 2D array :
int (*p)[column] = malloc (sizeof(int[row][column]);
An int ** can be allocated whereas int [][] is a temporary array defined only in the scope of your function.
Don't forget that a semicolon is needed at the end of nearly every line.
You should read this page for a more complete explanation of the subject
(and 2.)
If I have a 2-D array
int array_name[num_rows][num_columns];
So it consists of num_rows arrays -each of which is an array of size = num_columns.
If both num_rows and num_columns are known at compile time, that line declares an array of num_rows arrays of num_columns ints, which, yes, is commonly referred as a 2D array of int.
Since C99 (and optionally in C11) you can use two variables unknown at compile time and end up declaring a Variable-Length Array, instead.
Its equivalent representation using an array of pointers is
int* array_name[num_rows];
So the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right?
Technically, now array_name is declared as an array of num_rows pointers to int, not arrays. To "complete" the "2D array", one should traverse the array and allocate memory for each row. Note that the rows could have different sizes.
Using this form:
int (*array_name)[num_columns];
// ^ ^ note the parenthesis
array_name = malloc(num_rows * sizeof *array_name);
Here, array_name is declared as a pointer to an array of num_columns ints and then the desired number of rows is allocated.
3.
what if p was defined as int **p;
The other answers show how to allocate memory in this case, but while it is widely used, it isn't always the best solution. See e.g.:
Correctly allocating multi-dimensional arrays
I want to create 5*5 2D Matrix. I usually use the following way of memory allocation:
int **M = malloc(5 * sizeof(int *));
for (i = 0; i < 5; i++)
{
M[i] = malloc(5 * sizeof(int));
}
While I was reading a blog, I found also another way to do that:
int **M = malloc(5 * sizeof(int*));
M[0] = malloc((5*5) * sizeof(int));
My question is: What is the difference between both methods? Which one in more efficient?
For the second code, note that you need to initialize the other array members for it to work correctly:
for (int i = 1; i < 5; i++) {
M[i] = M[0] + i * 5;
}
So in the second code the arrays members (through all arrays) are contiguous. It does not make any difference to access them (e.g., you an still access them using M[i][j] syntax). It has the advantage over the first code to require only two malloc calls and as mentioned in the comments to favor caching which can greatly improve the access performances.
But if you plan to dynamically allocate large arrays, it is better to use the first method because of memory fragmentation (large contiguous memory allocation can be not available or can exacerbate memory fragmentation).
A similar example of this kind of dynamic allocation of arrays of arrays can be found in the c-faq: http://c-faq.com/aryptr/dynmuldimary.html
After seeing ouah's answer and seeing the example in the C FAQ, I now understand where the second technique comes from, although I personally wouldn't use it where I could help it.
The main problem with the first approach you show is that the rows in the array are not guaranteed to be adjacent in memory; IOW, the object immediately following M[0][4] is not necessarily M[1][0]. If two rows are allocated from different pages, that could degrade runtime performance.
The second approach guarantees that all the rows will be allocated contiguously, but you have to manually assign M[1] through M[4] to get the normal M[i][j] subscripting to work, as in
for ( size_t i = 0; i < 5; i++ )
M[i] = M[i-1] + 5;
IMO it's a clumsy approach compared to the following:
int (*M)[5] = malloc( sizeof *M * 5 );
This also guarantees that the memory is allocated contiguously, and the M[i][j] subscripting works without any further effort.
However, there is a drawback; on compilers that don't support variable-length arrays, the array size must be known at compile time. Unless your compiler supports VLAs, you can't do something like
size_t cols;
...
int (*M)[cols] = malloc( sizeof *M * rows );
In that case, the M[0] = malloc( rows * cols * sizeof *M[0]) followed by manually assigning M[1] through M[rows - 1] would be a reasonable substitute.
I hope I'm not missing something here but here's my attempt to answer the question "What is the difference...". If I am completely off base, forgive me and I will correct my answer but here goes:
I tried drawing out what is happening in your two mallocs so what I have to say is tied to the picture included which I drew by hand (hand crafted answers?)
First option:
For the first option, you allocate a memory block the size of 5 int*s. M, which is an int** points to the start of that memory block.
Then, you go over each of the memory blocks (the size of int*) and in each block you put in the address of a memory block the size of 5 ints. Note that these are located in some random portion of your memory (the heap) that has enough space to take the size of 5 ints.
This is the key - it's a noncontiguous block of memory. So if you think about memory as an array, you are pointing at different start locations in the array.
Second Option
Your second does the allocation of int** exactly the same. But instead, it allocates the size of 25 ints and returns places the address of that array in the memory block M[0]. Note: you've never placed any address in the memory locations M[1] - M[4].
So, what happens? You have a contiguous block of 25 ints with an address that can be found in M[0]. What happens when you try getting M[1]? You guessed it - it's empty or contains junk values. Even more, it's a value that does not point to an allocated memory space so you Segfault.
If you want to allocate a 5x5 array in contiguous memory, the correct approach would be
int rows = 5;
int cols = 5;
int (*M)[cols] = malloc(rows * sizeof(*M));
You can then access the array with normal array indexing, e.g.
M[3][2] = 6;
int **M = malloc(5 * sizeof(int *)); refers to allocating memory for a pointer M[i] = malloc(5 * sizeof(int)); refers to allocating memory for a variable of int.
Maybe this will help you understand what is going on:
int **M = malloc(5 * sizeof(void *));
/* size of 'void *' and size of 'int *' are the same */
for (i = 0; i < 5; i++)
{
M[i] = malloc(5 * sizeof(int));
}
Another little difference when using malloc((5*5) * sizeof(int));. Certainly a side issue to what OP is looking for, but still a concern.
Both of the below are the same as the order of the 2 operands still result in using size_t math for the product.
#define N 5
malloc(N * sizeof(int));
malloc(sizeof(int) * N);
Consider:
#define N some_large_value
malloc((N*N) * sizeof(int));
The type of the result of sizeof() is type size_t, an unsigned integer type, that is certainly has SIZE_MAX >= INT_MAX, possible far larger. so to avoid int overflow that does not overflow size_t math use
malloc(sizeof(int) * N * N);
In this code, the "array" is an array of pointers to chars? Or something else?
struct tmep{
char (*array) [SIZE];
}
Thanks in advance :)
It's a pointer to an array of SIZE chars.
Declaration mimics use, so you evaluate the parenthesis first, (*array) gives you a char[SIZE].
To allocate, the stable version is as usual
array = malloc(num_elements * sizeof *array);
to specify the size of each object (char[SIZE] here) in the block by taking the sizeof the dereferenced pointer. You don't need to change that allocation if the type changes e.g. to int (*)[SIZE].
If you want to specify the type,
array = malloc(num_elements * sizeof(char (*)[SIZE]));
This allocates - if malloc succeeds - a block large enough for num_elements arrays of SIZE chars, each of these arrays is accessed with
array[i]
and the chars in the arrays in the block with
array[i][j]
I have dynamically allocated 2D array.
Here is the code
int **arrofptr ;
arrofptr = (int **)malloc(sizeof(int *) * 2);
arrofptr[0] = (int *)malloc(sizeof(int)*6144);
arrofptr[1] = (int *)malloc(sizeof(int)*4800);
Now i have to know that how many bytes are allocated in arrofptr,arrofptr[0],arrofptr[1]?
is there any way to know the size?
if we will print
sizeof(arrofptr);
sizeof(arrofptr[0]);
sizeof(arrofptr[1]);
then it will print 4.
You can't find size of arrofptr, because it is only a pointer to pointer. You are defining an array of arrays using that. There's no way to tell the size information with only a pointer, you need to maintain the size information yourself.
The only return value you get from malloc() is a pointer to the first byte of the allocated region (or NULL on failure). There is no portable, standard, way of getting the associated allocation size from such a pointer, so in general the answer is no.
The C way is to represent arrays and buffers in general with a pair of values: a base address and a size. The latter is typically of the type size_t, the same as the argument to malloc(), by the way.
if you want to keep track of the size of an allocated block of code you would need to store that information in the memory block that you allocate e.g.
// allocate 1000 ints plus one int to store size
int* p = malloc(1000*sizeof(int) + sizeof(int));
*p = (int)(1000*sizeof(int));
p += sizeof(int);
...
void foo(int *p)
{
if (p)
{
--p;
printf( "p size is %d bytes", *p );
}
}
alt. put in a struct
struct
{
int size;
int *array;
} s;
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the pointer, and thus your calculation the size of the pointers is usually 4, this is why you got 4 and is likely to have the trivial result of 4, always.
int **arrayPtr;
arrayPtr = malloc(sizeof(int) * rows *cols + sizeof(int *) * rows);
In the above code, we are trying to allocate a 2D array in a single malloc call.
malloc takes a number of bytes and allocates memory for that many bytes,
but in the above case, how does malloc know that first it has to allocate a array of pointers, each of which pointer points to a one-dimensional array?
How does malloc work internally in this particular case?
2D arrays aren't the same as arrays of pointers to arrays.
int **arrayPtr doesn't define a 2D array. 2D arrays look like this:
int array[2][3]
And a pointer to the first element of this array would look like:
int (*array)[3]
which you can point to a block of memory:
int (*array)[3] = malloc(sizeof(int)*5*3);
Note how that's indexed:
array[x] would expand to *(array+x), so "x arrays of 3 ints forward".
array[x][y] would expand to *( *(array+x) + y), so "then y ints forward".
There's no immediate array of pointers involved here, only one contignous block of memory.
If you'd have an array of arrays (not the same as 2D array, often done using int** ptr and a series of per-row mallocs), it would go like:
ptr[x] would expand to *(array+x), so "x pointers forward"
ptr[x][y] would expand to *( *(array+x) + y) = "y ints forward".
Mind the difference. Both are indexed with [x][y], but they are represented in a different way in memory and the indexing happens in a different manner.
how does malloc know that first it has to allocate a array of pointers, each of which pointer points to a one-dimensional array?
It doesn't; malloc simply allocates the number of bytes you specify, it has no working knowledge of how those bytes are structured into an aggregate data type.
If you're trying to dynamically allocate a multidimensional array, you have several choices.
If you're using a C99 or C2011 compiler that supports variable length arrays, you could simply declare the array as
int rows;
int cols;
...
rows = ...;
cols = ...;
...
int array[rows][cols];
There are a number of issues with VLAs, though; they don't work for very large arrays, they can't be declared at file scope, etc.
A secondary approach is to do something like the following:
int rows;
int cols;
...
rows = ...;
cols = ...;
...
int (*arrayPtr)[cols] = malloc(sizeof *arrayPtr * rows);
In this case, arrayPtr is declared as a pointer to an array of int with cols elements, so we're allocating rows arrays of cols elements each. Note that you can access each element simply by writing arrayPtr[i][j]; the rules of pointer arithmetic work the same way as for a regular 2D array.
If you aren't working with a C compiler that supports VLAs, you'll have to take a different approach.
You can allocate everything as a single chunk, but you'll have to access it as a 1-d array, computing the offsets like so:
int *arrayPtr = malloc(sizeof *arrayPtr * rows * cols);
...
arrayPtr[i * rows + j] = ...;
Or you can allocate it in two steps:
int **arrayPtr = malloc(sizeof *arrayPtr * rows);
if (arrayPtr)
{
int i;
for (i = 0; i < rows; i++)
{
arrayPtr[i] = malloc(sizeof *arrayPtr[i] * cols);
if (arrayPtr[i])
{
int j;
for (j = 0; j < cols; j++)
{
arrayPtr[i][j] = some_initial_value();
}
}
}
}
malloc() does not know that it needs to allocate an array of pointers to arrays. It simply returns a chunk of memory of the requested size. You can certainly do the allocation this way, but you'll need to initialize the first "row" (or last, or even a column instead of a row - however you want to do it) that are to be used as pointers so that they point to the appropriate area within that chunk.
It would be better and more efficient to just do:
int *arrayPtr = malloc(sizeof(int)*rows*cols);
The downside to that is that you have to calculate the proper index on every use, but you could write a simple helper function to do that. You wouldn't have the "convenience" of using [] to reference an element, but you could have e.g. element(arrayPtr, x, y).
I would re-direct your attention rather to question of "what does [] operator do?".
If you plan to access elements in your array via [] operator, then you need to realize that it can only do off-setting based on element's size, unless some array geometry info is supplied.
malloc does not have provisions for dimension info, calloc - explicitly 1D.
On the other hand, declared arrays (arr[3][4]) explicitly specify the dimensions to the compiler.
So to access dynamically alloc'ed multi-D arrays in a fashion arr[i][j], you in fact allocate the series of 1D-arrays of the target dimension size. You will need to loop to do that.
malloc returns plain pointer to heap memory, no information about geometry or data-type. Thus [][] won't work, you'll need to the offsetting manually.
So it's your call whether []-indexing is your priority, or the bulk allocation.
int **arrayPtr; does not point to a 2D array. It points to an array of pointers to int. If you want to create a 2D array, use:
int (*arrayPtr)[cols] = calloc(rows, sizeof *arrayPtr);