0

If I take the 2 following snipped codes below (which are equivalent) :

double ***x;
x = malloc(N * sizeof(*x));
for (i = 0; i < size_y; i++) {
   x[i] = malloc(N * sizeof(**x));

and

double ***x;
x = malloc(N * sizeof(double*));
for (i = 0; i < size_y; i++) {
   x[i] = malloc(N * sizeof(double**));

Does the syntax for the first one above should be rather :

double ***x;
x = malloc(N * sizeof(*x));
for (i = 0; i < size_y; i++) {
   x[i] = malloc(N * sizeof(*x));

I mean, for x, x[i] and x[i][j] malloc allocation, syntax will stay "sizeof(*x)", is this right ?

??

and does the second one should be :

double ***x;
x = malloc(N * sizeof(double**));
for (i = 0; i < size_y; i++) {
   x[i] = malloc(N * sizeof(double*));

??

I saw this syntax from this link

It is safer becuse you don't have to mention the type name twice and don't have to build the proper spelling for "dereferenced" version of the type. For example, you don't have to "count the stars" in

int *****p = malloc(100 * sizeof *p);

Compare that to the type-based sizeof in

int *****p = malloc(100 * sizeof(int ****));

where you have too make sure you used the right number of * under sizeof.

regards

UPDATE 1 :

I have got in one answer below the syntax as a pattern :

p = malloc(N * sizeof *p);

Does spaces (between N, sizeof and *p) and the abscence of parenthsesis for sizeof *p (instead of sizeof(*p)) have to be strictly applied for syntax of this allocation ?

In my code, I did :

 /* Arrays */
  double**  x;
  double**  x0;

/* Allocation of 2D arrays */
  x =  malloc(size_tot_y*sizeof(*x));
  x0 =  malloc(size_tot_y*sizeof(*x0));

  for(i=0;i<=size_tot_y-1;i++)
  {
    x[i] = malloc(size_tot_x*sizeof(**x));
    x0[i] = malloc(size_tot_x*sizeof(**x0));
  }

As you can see, I used parenthesis for sizeof and didn't use spaces between size_tot_*, sizeof and *p.

Does my syntax change anything to respect the pattern mentioned above ?

It may be a silly question but I would like to get a confirmation.

Thanks

Community
  • 1
  • 1
youpilat13
  • 83
  • 5
  • 29
  • 89
  • 3
    The first snippet is correct, the second snippet is not, and the third snippet is not. The sizes of `double*` and `double**` are not guaranteed to be the same in C (even though they usually are the same) and it’s confusing to use the wrong type in `sizeof` anyway. – Ry- Feb 01 '17 at 04:27
  • 1
    The argument about not having to count stars doesn’t hold much weight, either, because if you’re going beyond `**` too often you’re probably doing something wrong. – Ry- Feb 01 '17 at 04:27
  • Also `i < size_y;` --> `i < N;` or `x = malloc(N * sizeof(*x));` --> `x = malloc(size_y * sizeof(*x));` – BLUEPIXY Feb 01 '17 at 04:32
  • ok thanks. and what about the right syntax for the second snippet ? – youpilat13 Feb 01 '17 at 04:33
  • @Ryan, so the fourth sinppet is right compared to the second one ? – youpilat13 Feb 01 '17 at 04:43
  • 1
    @youpilat13: Yes. – Ry- Feb 01 '17 at 04:52

2 Answers2

1

The pattern is:

p = malloc(N * sizeof *p);

Replace p with the same thing in both cases. For example:

x[i] = malloc(N * sizeof *x[i]);

Sometimes people abbreviate *x[i] to **x using the knowledge that **x means *x[0], and x[0] and x[i] have the same size because all elements of an array must have the same type and therefore the same size.

But if you are not confident about all this then you can stick to the basic pattern and use *x[i].

M.M
  • 134,614
  • 21
  • 188
  • 335
-1

There are 2 things,

  • Pointer holds the address of allocated space and
  • malloc() allocates the space what size is provided. so, malloc(1) will allocate 1 byte, malloc(sizeof(double)) will allocate number of bytes(may be 8 bytes) that needs for double, malloc(sizeof(double *)) will allocate number of bytes(may be 4 bytes) that needs for that address.

So, For 1st reference,

double *d1 = (double *) mallloc(sizeof(double)); // for single value

or,

double *d1 = (double *) malloc(N * sizeof(double));  // for array

Similiarly for 2nd referenece,

double **d2 = (double **) malloc(N * sizeof(double *));

And for 3rd reference,

double ***d3 = (double ***) malloc(N * sizeof(double *));

Now, we can consider,

void mallocTest()
{
    const int N = 10;
    double ***x;

    x = (double ***)malloc(N * sizeof(double *));
    for (int i = 0; i < N; i++) {
        x[i] = (double **)malloc(N * sizeof(double *));
        for (int j = 0; j < N; j++) {
            x[i][j] = (double *)malloc(sizeof(double));       // for single value;
            //x[i][j] = (double *)malloc(N * sizeof(double));    // for array, here N == 10 elements

            *x[i][j] = i*j;  // or
            //x[i][j][0] = i*j;
        }
    }

    for (int i = 0; i < N; i++){
        for (int j = 0; j < N; j++){
            //printf("%f ", *x[i][j]);     // or
            printf("%f ", x[i][j][0]);
        }
        printf("\n");
    }
}
  • d3 holds 3rd reference address. Is the number of bytes not equal for any type of address? – Salah Uddin Feb 01 '17 at 10:00
  • could you pls explain, why can't I use `double *` to get size of address. – Salah Uddin Feb 01 '17 at 10:09
  • The outermost array has elements of type `double **`. When allocating space for an array of `T`'s you should use `sizeof(T)` to get the size of each element. Having `T` = `double **` is not a special case. – M.M Feb 01 '17 at 10:37
  • well you aren't. The type you specify in `sizeof` should be the same type as what you are actually allocating for, but your code uses a different type – M.M Feb 01 '17 at 20:46
  • malloc will allocate number of bytes what I've specified. Where number of bytes for address will be same for any type. Then I've casted the size of bytes to my needed type. – Salah Uddin Feb 04 '17 at 05:19
  • different pointer types may have different sizes, e.g. `char *` could be 5 bytes and `char **` could be 4 bytes – M.M Feb 04 '17 at 05:19
  • In my machine, `char *`, `char **`, `float *`, `double *`, `int *` all takes 4 bytes. – Salah Uddin Feb 04 '17 at 06:32
  • My version also works on all machines. The value could differ machine(32 bit operating system or windows or linux) to machine(64 bit operating machine or linux or windows) but should not in same machine. – Salah Uddin Feb 04 '17 at 08:17
  • yours would not work on a machine with `sizeof(double *) < sizeof(double **)` – M.M Feb 04 '17 at 08:38
  • after crossing a desert you are telling me `sizeof(double *) < sizeof(double **)` when I'm telling you whole the way `sizeof(double *) == sizeof(double **)` in a same machine. – Salah Uddin Feb 04 '17 at 09:41
  • Yes, read the C Standard. It does not say that all pointers are the same size. – M.M Feb 05 '17 at 06:32
  • Salah Uddin: could you see my remark into my **UPDATE 1**, this is for a confirmation, thanks – youpilat13 Mar 29 '17 at 03:27