Why the code "RGBTRIPLE (*image)[width]" initialises a 2D array?

Viewed 368

This code is from the CS50 course, pset4, the "Filters" task. The concept is following:

  1. open an image file (BMP)
  2. read all pixels to a 2D array, where 1-st lvl is a height, and 2-nd lvl is a width

The code is next:

// height, width are image`s property
// RGBTRIPLE is an entity (struct) of a pixel

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

...

for (int i = 0; i < height; i++)
{
    // Read row into pixel array
    fread(image[i], sizeof(RGBTRIPLE), width, inptr);

    ...
}

I understand that:

  1. we create a pointer *image
  2. we allocate enough memory for 2d array: calloc(height, width * sizeof(RGBTRIPLE))

But what (*image)[width] means? Shouldn't it be a pointer to the width length array? If so, why later we iterate through the image height and fill the width length array?

One guy on Reddit wrote: "RGBTRIPLE (*image)[width] declares that image is a pointer to one or more arrays". And it starts making sense then. But I can't get where this "...or more arrays" part?

1 Answers

This line

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

declares a pointer of the type RGBTRIPLE(*)[width] that is a pointer to an object of the type RGBTRIPLE[width].

The call of calloc may be rewritten like

RGBTRIPLE(*image)[width] = calloc(height, sizeof(RGBTRIPLE[width]));

provided that the compiler supports variable length arrays. That is in this call there is allocated height one-dimensiobal arrays of the type RGBTRIPLE[width] i.e a two-dimensional array.

Or you could even write

RGBTRIPLE(*image)[width] = calloc( 1, sizeof(RGBTRIPLE[height][width]));

To make it clear consider for example the declaration of a two-dimensional array.

RGBTRIPLE image[height][width];

then the array designator image used in expressions (with rare exceptions) is converted to pointer to its first element. The type of elements of the array is RGBTRIPLE [width]. So the type of a pointer to the first element of the array is RGBTRIPLE ( * )[width].

As for this part

But I can't get where this "...or more arrays" part?

then strictly speaking it is incorrect. A pointer can point to one object. But you can allocate an array and the returned pointer will point to the first element of the allocated array.

For example in this declaration

RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));

there are allocated height one-dimensional arrays where height can be any non-negative number including for example 1.

Related