Casting uint16_t to unsigned int

Viewed 316

We have casted 2d array:

struct pixel(*image_data)[width] = (struct pixel(*)[width])img->px;
  1. I didn't get how it casts and allocate memory?

where width:

  unsigned width = img->size_x;

and struct image:

struct image {
   uint16_t size_x;
   uint16_t size_y;
   struct pixel *px;
};

2nd question:

What is maximum value that width can hold?

3rd:

If we iterate image_data[x][y] where x and y are long then there is buffer overflow?

1 Answers
  1. The cast doesn't allocate memory. The type of the image_data variable is "pointer to array of length width of struct pixel" (using the value of width at the point of declaration of image_data), so image_data + i is a pointer to the ith row (counting from 0) of struct pixel.

  2. In theory, width could be any value up to SIZE_MAX / sizeof (struct pixel) but may be limited by other constraints. Also size_x and size_y in struct image are limited by their type uint16_t to a maximum value of 65535.

  3. If x >= 0 and y >= 0 and y < width (where width still has the value sizeof (*image_data) / sizeof ((*image_data)[0])) and the buffer pointed to by img->px is at least sizeof (struct pixel) * (x + 1) * width bytes long (and correctly aligned for struct pixel) then there will be no buffer overrun.

Regarding the definition of the width variable:

unsigned width = img->size_x;

img->size_x has type uint16_t and the maximum value of uint16_t is exactly 65535. width has type unsigned int and the maximum value of unsigned int is at least 65535, so width will be initialized to the value of img->size_x without truncation.

In the comments to the question, Lundin mentions that struct Pixel * is not compatible with struct pixel(*)[width]. That is true, but C allows conversion from one pointer type to another. The behavior is undefined if the resulting pointer is not correctly aligned for the referenced type (the referenced type is struct pixel [width] here). It would be highly unusual for an array type to have stricter alignment requirements than the corresponding element type, so that is probably OK. Even if the array type has a stricter alignment requirement than the element type, it is OK as long as the pointer is in fact correctly aligned. If img->px points to a block allocated by malloc, calloc or similar, then it is correctly aligned for any object type that has a "fundamental" alignment, so that is OK. The main problem is that if the pixel data is accessed via both img->px and image_data then that would violate the strict aliasing rule because the pointers have incompatible types.

Related