Problem with dynamic allocation of memory - c

Until now I did allocate the memory for a matrix like this :
int **p,n;
scanf("%d",&n);
p=malloc(n*sizeof(int));
for(int i=0;i<n;i++)
p[i]=malloc(n*sizeof(int));
but someone told me to do like this :
int **p,n;
scanf("%d",&n);
p=malloc(n*sizeof*p);
for(int i=0;i<n;i++)
p[i]=malloc(n*sizeof*p);
sizeof(p) is not 0 because is not allocated ??
Which one is good ?

In the first code snippet, this statement is wrong:
p=malloc(n*sizeof(int));
because the type of p is int **, so, p can be pointer to a int *
type. It should be:
p = malloc (n * sizeof (int *));
^^^^^
In the second code snippet, allocation to p is correct because of this - sizeof*p. The type of *p is int *. So, sizeof*p is equivalent to sizeof (int *).
But in second code snippet, this is wrong:
p[i]=malloc(n*sizeof*p);
because the type of p[i] is int * i.e. pointer to an int. So, it can point to an integer. Hence, you should allocate memory of n * sizeof (int). It should be
p[i] = malloc (n * sizeof *p[i]);
Here, n * sizeof *p[i] is equivalent to n * sizeof (int) because the type of *p[i] is int.
Its matter of choice to use whichever style you want to. The matter of fact is that, you should have a good understanding of what you are doing and how it works because the lack of understanding can result in mistake in any style that you choose (as you can see there is mistake in both the code snippets you have shown).

First of all, p=malloc(n*sizeof(int)); is wrong - you aren't allocating a 2D array but an array of pointers, each pointing to an array of int. This needs to be p=malloc(n*sizeof(int*)); for the first example to be correct.
Apart from that bug, this is a matter of subjective coding style. Some prefer to write malloc(n*sizeof*p); since sizeof *p gives the size of the pointed-at item. This works because sizeof isn't evaluated for side effects, so no pointer de-referencing actually happens. The size is computed at compile-time.
A third style is also possible: p=malloc( sizeof(int*[n]) );. Here you make it more explicit that you are declaring an array. Which of these three styles to use is subjective and mostly a matter of opinion.
And in case you want to allocate actual 2D arrays allocated adjacently, you need to do as advised here instead: Correctly allocating multi-dimensional arrays

Related

Allocate 6xNxN array

I have a variable N. I need a 6xNxN array.
Something like this:
int arr[6][N][N];
But, obviously, that doesn't work.
I'm not sure how I'd go about allocating this so that I can access, e.g. arr[5][4][4] if N is 5, and arr[5][23][23] if N is 24.
Note that N will never change, so I'll never have to reallocate arr.
What should I do? Will int ***arr = malloc(6 * N * N * sizeof(int)); work?
You can allocate your 3-dimensional array on the heap as
int (*arr)[N][N] = malloc(sizeof(int[6][N][N]));
After use, you can free as
free(arr);
Another way of writing the same as suggested by #StoryTeller is -
int (*arr)[N][N] = malloc(6u * sizeof(*arr));
But here you need to be careful about the u after 6 to prevent signed arithmetic overflow.
Also, there can still be issues on platforms where size_t is smaller in width that int as suggested by #chqrlie, but that won't be the case on "most" commonly used platforms and hence you are fine using it.
int arr[6][N][N]; will work just fine. You merely need to update your compiler and C knowledge to the year 1999 or later, when variable-length arrays (VLA) were introduced to the language.
(If you have an older version of GCC than 5.0, you must explicitly tell it to not use an ancient version of the C standard, by passing -std=c99 or -std=c11.)
Alternatively if you need heap allocation, you can do:
int (*arrptr)[Y][Z] = malloc( sizeof(int[X][Y][Z]) );
You cannot do int ***arr = malloc(6 * N * N * sizeof(int)); since a int*** cannot point at a 3D array. In general, more than two levels of indirection is a certain sign that your program design is completely flawed.
Detailed info here: Correctly allocating multi-dimensional arrays.
What you want can't work directly. For indexing a multi-dimensional array, all but the very first dimension need to be part of the type and here's why:
The indexing operator operates on pointers by first adding an index to the pointer and then dereferencing it. The identifier of an array evaluates to a pointer to its first element (except when e.g. used with sizeof, _Alignof and &), so indexing on arrays works as you would expect.
It's very simple in the case of a single-dimension array. With
int a[42];
a evaluates to a pointer of type int * and indexing works the following way: a[18] => *(a + 18).
Now in a 2-dimensional array, all the elements are stored contiguously ("row" after "row" if you want to understand it as a matrix), and what's making the indexing "magic" work is the types involved. Take for example:
int a[16][42];
Here, the elements of a have the type int ()[42] (42-element array of int). According to the rules above, evaluating an expression of this type in most contexts again yields an int * pointer. But what about a itself? Well, it's an array of int ()[42] so a will evaluate to a pointer to 42-element array of int: int (*)[42]. Then let's have a look at what the indexing operator does:
a[3][18] => *(*(a + 3) + 18)
With a evaluating to the address of a with type int (*)[42], this inner addition of 3 can properly add 42 * sizeof(int). This would be impossible if the second dimension wasn't known in the type.
I guess it's simple to deduce the example for the n-dimensional case.
In your case, you have two possibilities to achieve something similar to what you want.
Use a dynamically allocated flat array with size 6*N*N. You can calculate the indices yourself if you save N somewhere.
Somewhat less efficient, but yielding better readable code, you could use an array of pointers to arrays of pointers to int (multiple indirection). You could e.g. do
int ***a = malloc(6 * sizeof *int);
for (size_t i = 0; i < 6; ++i)
{
a[i] = malloc(N * sizeof *(a[i]));
for (size_t j = 0; j < N ++j)
{
a[i][j] = malloc(N* sizeof *(a[i][j]));
}
}
// add error checking to malloc calls!
Then your accesses will look just like those to a normal 3d array, but it's stored internally as many arrays with pointers to the other arrays instead of in a big contiguous block.
I don't think it's worth using this many indirections, just to avoid writing e.g. a[2*N*N+5*N+4] to access the element at 2,5,4, so my recommendation would be the first method.
Making a simple change to the declaration on this line and keeping the malloc can easily solve your problem.
int ***arr = malloc(6 * N * N * sizeof(int));
However, int *** is unnecessary (and wrong). Use a flat array, which is easy to allocate:
int *flatarr = malloc(6 * N * N * sizeof(int));
This works for three dimensions, and instead of accessing arr[X][Y][Z] as in the question, you access flatarr[(X*N*N) + (Y*N) + Z]. In fact, you could even write a handy macro:
#define arr(X,Y,Z) flatarr[((X)*N*N) + ((Y)*N) + (Z)]
This is basically what I've done in my language Cubically to allow for multiple-size cubes. Thanks to Programming Puzzles & Code Golf user Dennis for giving me this idea.

Right syntax with malloc : sizeof(*int) or sizeof(int*)

I usually see the syntax for malloc allocation :
int **p = malloc(N*sizeof(int*))
with p being a pointer. I have also seen the following syntax (maybe my sources are not right) :
int **p = malloc(N*sizeof(*int))
The difference between 2 syntax above is that "star" * appears after the type int for the first and before for the second one.
Could you tell me the right syntax between the two above?
The second one can be used only with an expression as the operand of the sizeof operator (and *int is not an expression, it's a syntax error).
You probably have seen it in code that uses the canonical way to allocate a dynamic array of N members of an arbitrary type:
p = malloc (N * sizeof *p);
I deliberately do not show the declaration of the pointer type p, since it is not needed. Even if the type of p changes, you never need to touch this allocation line. It always does the right thing.
C grammar sizeof quirk: with an expression operand, the parentheses are optional. They are required when the operand is a type.
None of the above is right for enough amount of memory. Below is correct:
int *p = malloc(N * sizeof(int));
or
int **p = malloc(N * sizeof(int *));
In the first one, you allocate memory for integers and you return it as pointer. The second is allocating array of pointers so you need * character in sizeof keyword.
But for messing in future of sizes, if you change int *p to let's say char *p, it is better to use this syntax:
int *p = malloc(N * sizeof(*p));
TL;DR The first one, partially (considering you have the terminating ; in your actual code).
Probably a better Correct way to write it will be
int *p = malloc(N*sizeof(*p)); // need memory for "int" type, not pointer to int
which removes the hard-coded dependency on the data type.
FWIW, the second one,
int *p = malloc(N*sizeof(*int))
is an erroneous statement, syntactical error.
And, to nitpick, it's not a "star", it's called a dereference operator.

What are the differences between *ptr and **ptr?

I am coding a 3D array using triple pointers with malloc. I replaced *ptrdate in (a), *ptrdate[i], and *ptrdate[i] with *ptrdate in the code below since They are all basically pointers of type Date but access in different dimension. I got the same results both ways.
Question: what's the difference when used as the operand of sizeof?
typedef struct {
int day;
} Date;
int main(){
int i, j, k, count=0;
int row=3, col=4, dep=5;
Date ***ptrdate = malloc(row * sizeof *ptrdate); //(a)
for (i=0; i<row; i++) {
ptrdate[i] = malloc(col * sizeof *ptrdate[i]); //(b)
for (j=0; j<col; j++) {
ptrdate[i][j] = malloc(dep * sizeof *ptrdate[i][j]); //(c)
}
}
I am coding a 3D array using triple pointers with malloc.
First of all, there is no need for any array to be allocated using more than one call to malloc. In fact, it is incorrect to do so, as the word "array" is considered to denote a single block of contiguous memory, i.e. one allocation. I'll get to that later, but first, your question:
Question: what's the difference when used as the operand of sizeof?
The answer, though obvious, is often misunderstood. They're different pointer types, which coincidentally have the same size and representation on your system... but they might have different sizes and representations on other systems. It is important to keep that possibility in mind, so that you can be sure your code is as portable as possible.
Given size_t row=3, col=4, dep=5;, you can declare an array like so: Date array[row][col][dep];. I know you have no use for such a declaration in this question... Bear with me for a moment. If we printf("%zu\n", sizeof array);, it'll print row * col * dep * sizeof (Date). It knows the full size of the array, including all of the dimensions... and this is exactly how many bytes are required when allocating such an array.
printf("%zu\n", sizeof ptrDate); with ptrDate declared as in your code will produce something entirely different, though... It'll produce the size of a pointer (to pointer to pointer to Date, not to be confused with pointer to Date or pointer to pointer to Date) on your system. All of the size information, regarding the number of dimensions (e.g. the row * col * dep multiplication) is lost, because we haven't told our pointers to maintain that size information. We can still find sizeof (Date) by using sizeof *ptrDate, though, because we've told our code to keep that size information associated with the pointer type.
What if we could tell our pointers to maintain the other size information (the dimensions), though? What if we could write ptrDate = malloc(row * sizeof *ptrDate);, and have sizeof *ptrDate equal to col * dep * sizeof (Date)? This would simplify allocation, wouldn't it?
This brings us back to my introduction: There is a way to perform all of this allocation using one single malloc. It's a simple pattern to remember, but a difficult pattern to understand (and probably appropriate to ask another question about):
Date (*ptrDate)[col][dep] = malloc(row * sizeof *ptrDate);
Suffice to say, usage is still mostly the same. You can still use this like ptrDate[x][y][z]... There is one thing that doesn't seem quite right, though, and that is sizeof ptrDate still yields the size of a pointer (to array[col][dep] of Date) and sizeof *ptrDate doesn't contain the row dimension (hence the multiplication in the malloc above. I'll leave it as an exercise to you to work out whether a solution is necessary for that...
free(ptrDate); // Ooops! I must remember to free the memory I have allocated!
int *ptr is the declaration of pointer which stores the address of the integer variable and int **ptr is the declaration that stores the address of the pointer storing the integer variable.

Dynamic memory allocation for 2D array

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().

Proper argument for malloc

I have always used the malloc function as, for exemple,
int size = 10000;
int *a;
a = malloc(size * sizeof(int));
I recently run into a piece of code that discards the sizeof(int) part, i.e.
int size = 10000;
int *a;
a = malloc(size);
This second code seems to be working fine.
My question is then, which form is correct? If the second form is, am I allocating needless space with the first form.
The argument to malloc is the number of bytes to be allocated. If you need space for an array of n elements of type T, call malloc(n * sizeof(T)). malloc does not know about types, it only cares about bytes.
The only exception is that when you allocate space for (byte/char) strings, the sizeof can be omitted because sizeof(char) == 1 per definition in C. Doing something like
int *a = malloc(10000);
a[9000] = 0;
may seem to work now, but actually exploits undefined behavior.
malloc allocates a given number of bytes worth of memory, suitably aligned for any type. If you want to store N elements of type T, you need N * sizeof(T) bytes of aligned storage. Typically, T * p = malloc(N * sizeof(T)) provides that and lets you index the elements as p[i] for i in [0, N).
From the man page:
The malloc() function allocates size bytes and returns a pointer to the allocated memory.
The first form is correct.
Even if the sizeof(int) on the machine you are targeting is one (which is sometimes true on 8-bit microcontrollers) you still want your code to be readable.
The reason the "second code seems to be working fine" is that you are lucky.
The version of malloc you are using might be returning a pointer to an area of memory that is larger than what you requested. No matter what is happening behind the scenes, the behavior may change if you switch to a different compiler, so you do not want to rely on it.

Resources