Search code examples
cmultidimensional-arraydynamic-memory-allocationcs50calloc

CS50 pset 4 smiley - what's the meaning of code line from license taks?


RGBTRIPLE (*image)[width] = calloc(height, width * sizeof(RGBTRIPLE)) I don't fully understand the code. What I understand is that:

  1. calloc(height, width * sizeof(RGBTRIPLE)) - we are organizing a place somewhere in heap memory of a certain size for certain data and set all values in this memory to 0
  2. RGBTRIPLE (*image)[width] means variable image is a pointer to an array of length width of RGBTRIPLE.
  3. RGBTRIPLE is a data structure that contains 3 variables: BYTE rgbtBlue; BYTE rgbtGreen; BYTE rgbtRed;

Why arrey is not created for two values: width and length but only for width. For me, this code shows that we have created only arrey [1d] and not as it should be [2d], that the image is 2d...

Below I am sending a drawing that I made for my reasoning.

enter image description here

trying to understand lines of code from pset CS50 smiley.


Solution

  • In fact in this line

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

    there is allocated a memory for a two-dimensional array of the type RGBTRIPLE[height][width] and its address is assigned to the declared pointer image. The memory allocated to the two-dimensional array is zero-initialized.

    Pay attention to that if you have a two-dimensional array like for example

    RGBTRIPLE array[height][width];
    

    then a pointer to the first element of the array is declared and initialized like

    RGBTRIPLE ( *image )[width] = array;
    

    That is the array designator used as an initialize expression is implicitly converted to pointer to its first element.

    In your case instead of assigning the pointer with an array it is assigned with the address of a dynamically allocated memory for a such an array.

    If the compiler supports variable length arrays then this line

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

    could be rewritten like

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

    From it it is seen that there are allocated memory for height(s) one-dimensional arrays of the type RGBTRIPLE[width] that is for a two-dimensional array of the type RGBTRIPLE[height][width].

    Thus dereferencing the pointer image like ( *image ) you will get the first "row" of the two-dimensional array. To access elements of that first row you can write for example ( *image )[0] or ( *image )[1] and so on. If elements of each "row" has a structure type then you can write for example as shown in your question ( *image )[0].rgbtBlue.