Bhagyesh
Bhagyesh

Reputation: 700

Unable to malloc for an object's variable that is a 2d array

I'm working on an assignment for class and having some issues with assigning values to an unsigned int ** variable that is in an object. For some reason, I can not assign it with malloc stating that there is an error with assignment to expression with array type. I'm not sure what this means, I have tried to use directly malloc it to image->pixmap, but have the same issue. This happens in both methods.

P.S. As this is an assignment I can NOT change the structs/object definitions, otherwise I would have.

I will do my best to explain the pixmap for PPMImage as an example:

pixmap: Three height x width, 2-dimensional pixel arrays, for ’R’, ‘G’, ‘B’ values
height: image height (number of rows)
width: image width (number of columns)
pixmax: maximum pixel value of image

//p->pixmap[0]: ‘R’ pixmap array
//p->pixmap[1][7]: 8th row of pixels of ‘G’ pixmap array
//p->pixmap[2][4][10]: 11th pixel in 5th row of ‘B’ pixmap array
typedef struct {
unsigned int ** pixmap[3];
unsigned int height, width, pixmax;
} PPMImage;

PPMImage * new_ppmimage( unsigned int w, unsigned int h, unsigned int m )
{

    PPMImage *image;
    image = (PPMImage *) malloc(sizeof(PPMImage));
    image -> height = h;
    image -> width = w;

    unsigned int ** tempArray = malloc(sizeof(unsigned int *)*h);
    for(int i  = 0;i < h; i++){
        tempArray[i] = malloc(sizeof(unsigned int) *w);
    }
    // issue here
    image -> pixmap = tempArray;
    return NULL;
}
=======================================
typedef struct {
unsigned int ** pixmap;
unsigned int height, width;
} PBMImage;

PBMImage * new_pbmimage( unsigned int w, unsigned int h )
{
    PBMImage *image;
    image = (PBMImage *) malloc(sizeof(PBMImage));
    image -> height = h;
    image -> width = w;
    
    // issue here
    image -> pixmap = malloc(sizeof(unsigned int *)*h);
    for(int i  = 0;i < h; i++){
        image -> pixmap[i] = malloc(sizeof(unsigned int) *w);
    }
    return NULL;
}

Upvotes: 1

Views: 133

Answers (2)

0___________
0___________

Reputation: 67546

Your code will never work as you always return NULL not the allocated memory in the new_ppmimage function.

If you cant change the types:

typedef struct {
unsigned int ** pixmap[3];
unsigned int height, width, pixmax;
} PPMImage;

PPMImage * new_ppmimage( unsigned int w, unsigned int h, unsigned int m )
{

    PPMImage *image;
    image = malloc(sizeof(*image));
    if(image)
    {
        image -> height = h;
        image -> width = w;
        for(size_t i = 0; i < sizeof(image -> pixmap) / sizeof(image -> pixmap[0]); i++)
        {
            image -> pixmap[i] = malloc(h * sizeof(*image -> pixmap));
            if(image -> pixmap)
            {
                for(unsigned hi = 0; hi < h; hi++)
                {
                    image -> pixmap[i][hi] = malloc(w * sizeof(**image -> pixmap[i]));
                    if(!image -> pixmap[hi])
                    {
                        /* handle memory allocation error */
                    }
                }
            }
        }
    }
    return image;
}

and the second one. See that there is almost no difference.

typedef struct {
unsigned int ** pixmap;
unsigned int height, width;
} PBMImage;

PBMImage * new_pbmimage( unsigned int w, unsigned int h)
{

    PBMImage *image;
    image = malloc(sizeof(*image));
    if(image)
    {
        image -> height = h;
        image -> width = w;
        image -> pixmap = malloc(h * sizeof(*image -> pixmap));
        if(image -> pixmap)
        {
            for(unsigned hi = 0; hi < h; hi++)
            {
                image -> pixmap[hi] = malloc(w * sizeof(**image -> pixmap));
                if(!image -> pixmap[hi])
                {
                    /* handle memory allocation error */
                }
            }
        }
    }
    return image;
}

I would implement it using flexible array members and array pointers. Only one malloc and free are needed. Much more efficient as two levels of indirection are removed.

typedef struct {
    size_t height, width, pixmax;
    unsigned int pixmap[][3];
} PPMImage;

PPMImage * new_ppmimage( const size_t w, const size_t h, unsigned int m )
{

    PPMImage *image;
    image =  malloc(sizeof(*image) +  h * w * sizeof(image -> pixmap[0]));
    if(image)
    {
        image -> height = h;
        image -> width = w;
    }
    return image;
}

And simple usage:

unsigned int getPixelVal(PPMImage *image, const size_t x, const size_t y, const size_t index)
{
    unsigned int (*pixel)[image -> width][3] = image -> pixmap;

    return pixel[y][x][index];
}

Upvotes: 1

Yun
Yun

Reputation: 3812

This

unsigned int ** pixmap[3];

means that pixmap is an array of size 3 containing values of the type "pointer to pointer to unsigned int". It is not possible to directly assign anything to an array type like this.

You probably want to do something like this:

image->pixmap[0] = tempArray;

This assigns tempArray to the first element of pixmap. Notice how the types of these match.

Repeat the allocation process to allocate memory for pixmap[1] and pixmap[2] as well.

Upvotes: 2

Related Questions