Search code examples
cpointersmultidimensional-arraymalloc

Using malloc to create triple pointer from 3d array to be passed to function which takes a triple pointer as an argument and updates its elements


I am currently attempting to create a triple pointer to point to and update the contents of a statically allocated 3d array in C. The updating of the elements of the array will be completed by a function like:

void effect_array(int ***ptr, int rows, int cols, int depth)
{
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            for(int k = 0; k < depth; k++)
            {
                ptr[i][j][k] *= 2;
            }
        }
    }
}

In the build up to my attempt I was successful at doing the following for a 2d/double pointer:

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

void effect_array2d(int **ptr, int rows, int cols)
{
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            ptr[i][j] *= 2;
        }
    }
}

int main()
{
    int arr[2][2] = {
        {1,2},
        {3,4}
    };
    
    int **ptr = (int **)malloc(2 * sizeof(int *));
    for(int i = 0; i < 2; i++) ptr[i] = arr[i];
    
    printf("Array before pass to effect_array2d:\n");
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    
    effect_array2d(ptr, 2, 2);
    
    printf("Array after pass to effect_array2d:\n");
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 2; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    
    free(ptr);
    
    return 0;
}

which gives an output of:

Array before pass to effect_array2d:
1 2 
3 4 

Array after pass to effect_array2d:
2 4 
6 8 

However when I try to use the same method for a 3d array and triple pointer:

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

void effect_array(int ***ptr, int rows, int cols, int depth)
{
    for(int i = 0; i < rows; i++)
    {
        for(int j = 0; j < cols; j++)
        {
            for(int k = 0; k < depth; k++)
            {
                ptr[i][j][k] *= 2;
            }
        }
    }
}

int main()
{
    int arr[2][2][2] = {
        {
            {1,2},
            {3,4}
        },
        {
            {5,6},
            {7,8}
        }
    };
    
    int ***ptr = (int ***)malloc(2 * sizeof(int **));
    for(int i = 0; i < 2; i++)
    {
        ptr[i] = arr[i];
    }
    
    free(ptr);

    return 0;
}

I am met with a warning stating that:

malloc3.c: In function ‘main’:
malloc3.c:34:16: warning: assignment to ‘int **’ from incompatible pointer type ‘int (*)[2]’ [-Wincompatible-pointer-types]
   34 |         ptr[i] = arr[i];
      |                ^

Not sure how to get around this, or what I am doing wrong. Any and all help is greatly appreciated.


Solution

  • I have seen this problem before, and it is a pretty tough one because C handles 3D arrays a little differently than it does the 2D ones. Here is what I did to solve the problem:

    #include <stdio.h>
    #include <stdlib.h>
    
    void effect_array(int ***ptr, int rows, int cols, int depth)
    {
        for(int i = 0; i < rows; i++)
        {
            for(int j = 0; j < cols; j++)
            {
                for(int k = 0; k < depth; k++)
                {
                    ptr[i][j][k] *= 2;
                }
            }
        }
    }
    
    int main()
    {
        int arr[2][2][2] = {
            {
                {1, 2},
                {3, 4}
            },
            {
                {5, 6},
                {7, 8}
            }
        };
    
        // Allocate memory for rows
        int ***ptr = (int ***)malloc(2 * sizeof(int **));
    
        // Allocate memory for columns in each row
        for(int i = 0; i < 2; i++)
        {
            ptr[i] = (int **)malloc(2 * sizeof(int *));
            for(int j = 0; j < 2; j++)
            {
                // Point to the correct part of the original array
                ptr[i][j] = &arr[i][j][0];
            }
        }
    
        
        printf("Array before:\n");
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 2; j++)
            {
                for(int k = 0; k < 2; k++)
                {
                    printf("%d ", arr[i][j][k]);
                }
                printf("\n");
            }
            printf("\n");
        }
    
        
        effect_array(ptr, 2, 2, 2);
    
        
        printf("Array after:\n");
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 2; j++)
            {
                for(int k = 0; k < 2; k++)
                {
                    printf("%d ", arr[i][j][k]);
                }
                printf("\n");
            }
            printf("\n");
        }
    
        
        for(int i = 0; i < 2; i++)
        {
            free(ptr[i]);
        }
        free(ptr);
    
        return 0;
    }
    

    The difference of this program using 2D arrays is that you have to handle two levels of memory allocation. After declaration, for each row, you have to reallocate for each column. After this, you can point to elements of the original array. The warning you are seeing arises because arr[i] in a 3D array isn't the same type as what ptr[i] expects. In this solution, we allocate memory for both rows and columns and then point to the actual data. and don’t forget to free the memory in the correct order to avoid leaks.