简体   繁体   中英

Variable size two dimensional array in C

So I've been trying to store a PPM file in a program to be manipulated, I successful stored everything up to the colors, I've made progress on the colors.

During asking a question on stack overflow ( For loop stops for no reason ) I was convinced that my method was a bit shoddy, however I don't understand the reasoning for using the follow:

COLOR (*colors)[width] = malloc( sizeof(COLOR[height][width]) );

can someone break down exactly what this line of code is doing and explain what type it is. So I can store it in a struct and successful return it.

Example: previously I used pointers to pointers, where I allocated a height and for each pointer I allocated a width. This means that for each pointer I could create a color, increment it along the width until Im at the end, then reset the pointer and increment the height and loop. After I got the full image I return it to store it in the follow:

typedef struct {
    char code[CODE_LENGTH];
    COMMENT *commentPPM;
    int width, height, max;
    COLOR **colorValues;
} PPM;

using:

ppmFile->colorValues = getColors(fd, ppmFile->width, ppmFile->height);

and

typedef struct{
    int red, green, blue;
} COLOR;

COLOR * getNextColor(FILE *fd);

COLOR **getColors(FILE *fd, int width, int height){
    printf("\nentered get colors");
    COLOR **colors = malloc(sizeof(COLOR*)*height);
    printf("\nallocated %d space height",height);

    int i,j;
    for(i = 0; i < height; i++, colors++){
        *colors = malloc(sizeof(COLOR)*width);
        printf("\nallocated %d space width",width);
        for(j = 0; j < width; j++, *(colors++)){
            printf("\nlooping through to get the colors for point (%d,%d)", j,i); 
            //*colors = getNextColor(fd);
        }
        *colors -= width;
        printf("\nmoved the pointer for *colors back %d spaces",width);
    }

    colors -= height;
    printf("\nmoved the pointer for colors back %d spaces",height);

    return colors;
}

In order to understand this, you need to first understand the concepts:

  • Array pointers (not to be confused with pointer to first element)
  • Variable-length arrays , also known as VLAs.

Given that already you know what the above is, then the most formally proper way to do this is to declare an array pointer to a 2D VLA:

COLOR (*colors)[height][width];

And when you call malloc, you tell it to allocate enough space for such an array:

malloc( sizeof(COLOR[height][width]) )

You would then end up with

colors = malloc( sizeof(COLOR[height][width]) );

However, since colors in this example is an array pointer, you would have to de-reference it each time you wish to access the array:

(*colors)[i][j] = something;

This syntax is not practical and also hard to read.

Therefore, you can use another trick and skip the inner-most dimension when you declare the array pointer. Instead of a pointer to a 2D array, you could skip the inner-most dimension and just declare an array pointer to a 1D array:

COLOR (*colors)[width]

but use this with the very same malloc call as before. Because now you can take advantage of array pointer arithmetic:

colors[i][j] = something;

Which essentially means, "in my array-of-arrays, give me array number i , item number j ".

It works for the same reason as int* x = malloc(sizeof(int[n])); ... x[i] = something; int* x = malloc(sizeof(int[n])); ... x[i] = something; works, which of course gives you int number i .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM