In some starter code we have:
/**
* RGBTRIPLE
*
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*
* Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
*/
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
and in our main program we have:
RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
I'm confused about (*image)
If I was to define a pointer to a RGBTRIPLE I thought I would use:
RGBTRIPLE *image[width] = ....
Is that the same as:
RGBTRIPLE(*image)[width] = .... ?
RGBTRIPLE *image[width];
Is an array of pointers to RGBTRIPLE
, this array will have width
number of elements. Each pointer in this array is capable of pointing to a RGBTRIPLE
object, that makes it possible to have a 2D array when you have several of these objects per row.
The allocation is messier because you would need to allocate the array of pointers themselves and then each row for which each pointer would be pointing to, and later deallocate the memory in reverse order.
RGBTRIPLE(*image)[width];
Is a pointer to array of RGBTRIPLE
, this array must have width
number of elements, that being the case you can use it to point to a 2D array with any number of rows as long as it has width
number of columns.
This is a better way of implenting a 2D array because it facilitates the allocation and deallocation.
This works by allowing it to move the pointer in blocks of width
size of bytes by incrementing it, in practice it let's you "jump" to the next row by incrementing the pointer once.
For example, an array of 6 of width
and 2 of height
:
+-----------+
image[0] -> |0|1|2|3|4|5|
+-----------+
|5|4|3|2|1|0|
+-----------+
+-> image[0][4]
|
+-----------+
|0|1|2|3|4|5|
+-----------+
image[1] -> |5|4|3|2|1|0|
+-----------+
|
+-> image[1][4]
The expression:
RGBTRIPLE(*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
could be better, I would use a safer method:
RGBTRIPLE(*image)[width] = calloc(height, sizeof *image);