0

I am attempting to write a procedure that lets me allocate a contiguous block of memory of size n1*n2*n3 and access it using 3 indices, like you would with an array

int array[n1][n2][n3];

I have successfully (as far as I can tell) managed this with two indices (see my example below)

#include <stdlib.h>

int main() {

    // Dimensions
    const int n1 = 2;
    const int n2 = 2;

    int **array;

    // Pointers
    array = (int **)malloc(n1*sizeof(int *));

    // Contiguous chunk of memory of size n1xn2
    array[0] = (int *)malloc(n1*n2*sizeof(int));

    // Pointer arithmetic
    for(int i=0;i<n1;i++) {
        array[i] = array[0] + i*n2;
    }

    array[0][0] = 1;

    return EXIT_SUCCESS;
}

But when I try a similar construct with three indices, my procedure throws a segfault:

#include <stdlib.h>

int main() {

    // Dimensions
    const int n1 = 2;
    const int n2 = 2;
    const int n3 = 2;

    int ***array;

    // Pointers
    array = (int ***)malloc(n1*sizeof(int **));
    array[0] = (int **)malloc(n1*n2*sizeof(int *));

    // Contiguous chunk of memory of size n1xn2xn3
    array[0][0] = (int *)malloc(n1*n2*n3*sizeof(int));

    // Pointer arithmetic
    for(int i=0;i<n1;i++) {
        for(int j=0;j<n2;j++) {
            array[i][j] = array[0][0] + i*n2*n3 + j*n2;
        }
    }

    array[0][0][0] = 1;

    return EXIT_SUCCESS;
}

I understand there are other ways to manage a contiguous block of memory. I am specifically interested in why my logic is failing in the above case.

DJames
  • 571
  • 3
  • 17
  • 1
    try just ` array = (int ***)malloc(n1**n2*n3*sizeof(int **));` – dehasi May 23 '18 at 16:24
  • 6
    You will need another loop for assigning `array[i]`, before assigning `array[i][j]`. – Eugene Sh. May 23 '18 at 16:24
  • 1
    Being C, you *can* do this using VLA addressing and a single allocation (assuming your toolchain actually supports it, you're SOL if using an MS tool set). So I'm not sure whether that's an option for you or not. – WhozCraig May 23 '18 at 16:56
  • Do not cast the return of `malloc`, it is unnecessary. See: [**Do I cast the result of malloc?**](http://stackoverflow.com/q/605845/995714) – David C. Rankin May 23 '18 at 17:24

2 Answers2

1

You are probably missing

array[i] = array[0] + i*n2;

Here is your code

#include <stdlib.h>

int main() {

    // Dimensions
    const int n1 = 2;
    const int n2 = 2;
    const int n3 = 2;

    int ***array;

    // Pointers
    array = (int ***)malloc(n1*sizeof(int **));
    array[0] = (int **)malloc(n1*n2*sizeof(int *));

    // Contiguous chunk of memory of size n1xn2xn3
    array[0][0] = (int *)malloc(n1*n2*n3*sizeof(int));

    // Pointer arithmetic
    for(int i=0;i<n1;i++) {
        array[i] = array[0] + i*n2;
        for(int j=0;j<n2;j++) {
            array[i][j] = array[0][0] + i*n2*n3 + j*n2;
        }
    }

    array[0][0][0] = 1;

    return EXIT_SUCCESS;
}
j123b567
  • 3,110
  • 1
  • 23
  • 32
  • Do not cast the return of `malloc`, it is unnecessary. See: [**Do I cast the result of malloc?**](http://stackoverflow.com/q/605845/995714) – David C. Rankin May 23 '18 at 17:19
-1

Allocating memory for 3D array. Maybe I did something wrong, but seems ok.

#include <stdlib.h>
#include <stdio.h>

int
main () {
 int n1 = 2;
 int n2 = 3;
 int n3 = 4;
 int i, j;

 int ***array;

 array = malloc(n1 * sizeof(int**));

 for (i = 0; i < n1; i++)
    array[i] = malloc(n2 * sizeof(int*));

 for (i = 0; i < n1; i++)
 for (j = 0; j < n2; j++)
    array[i][j] = malloc(n3 * sizeof(int));


 array[1][2][3] = 15000;
 printf("%d\n", array[1][2][3]);

return 0;
}
purec
  • 308
  • 2
  • 6
  • I don't think the memory would be contiguous in this example, as you are mallocing n1*n2 separate chunks of memory – DJames May 23 '18 at 16:41
  • 1
    @DJames your suspicions of discontinuity are well-founded. As soon as you introduce more than one `malloc` continuity goes out the window. This answer does not provide a single contiguous region (and neither does any of your posted code). – WhozCraig May 23 '18 at 16:45
  • @DJames True. But you can use indices. – purec May 23 '18 at 16:47
  • @WhozCraig: Well, this `array[0] = (int *)malloc(n1*n2*sizeof(int));` allocates a *continues* region of memory which holds *all* `int`s of the "2D"-array. – alk May 23 '18 at 16:50
  • @alk Of *that* array of arrays, but there are more than one (thus the loops). The backdrop of this, therefore, cannot be similar to `int arr[a][b][c];`, but you already knew that. – WhozCraig May 23 '18 at 16:55