The code implements a two-dimensional array as a pointer to pointers to int
, so it allocates space both for an array of r
pointers to int
and for the r
•c
int
objects. (This is generally bad practice as using pointers-to-pointers commonly has bad performance practice. In C implementations that support variable-length arrays, they are generally a better choice. Otherwise, calculating the indices into a one-dimensional array, as with i*c + j
to map indices [i][j]
to one dimension, is better for performance.)
Thus it needs sizeof (int *) * r
bytes for the pointers and sizeof (int) * c * r
bytes for the int
objects. However, it may also need padding between these to ensure proper alignment for the int
objects. In common C implementations, the amount of padding needed is zero, since the alignment of int
is commonly less than or equal to that of int *
. However, within the requirements of the C standard, it can be non-zero. So a proper amount of memory to allocate is:
sizeof (int *) * r + _Alignof (int) - 1 - (sizeof (int *) * r - 1) % _Alignof (int) + sizeof (int) * c * r
In this, _Alignof (int) - 1
is the maximum number of bytes we might need to pad (if we end just one byte after the designed multiple, we need to add _Alignof (int) - 1
to get to the next multiple), and (sizeof (int *) * r - 1) % _Alignof (int)
is how many bytes beyond one byte the space for the int *
goes, modulo _Alignof (int)
, so subtracting that from the maximum gives the number of bytes we need to get to the next multiple.