title: Why does pointer artihmetic work with non-contiguous 2d arrays?
body: <p>My understanding is that if one declares a 2d array locally as such: <code>int 2darr[x][y]</code>, it's not an array of pointers where each pointer points to a 1d array of its own, but instead it's a 1d array on which the processor does pointer arithmetic of the type <code>*(2darr + (row x nCols) + col)</code>.</p>
  
  <p>In that case, the pointer arithmetic behind the syntactic sugar <code>2darr[row][col]</code> makes sense because our 2d array is actually under the hood just a single contiguous block of memory of size <code>nRows x nCols</code>.</p>
  
  <p>However one way to dynamically allocate a 2d array is to first allocate an array of pointers of size <code>nRows</code>, and then for each of those pointers allocate an array of size <code>nCols</code> of whatever type we want. In that case our rows aren't necessarily stored contiguously in memory; each row could be stored at a completely different location in memory, with one of the pointers in our array of pointers pointing to its first element. </p>
  
  <p>Given that, I don't understand how we can still access data in the 2d array by doing <code>2darr[row][col]</code>. Since our rows aren't guaranteed to be stored contiguously, pointer arithmetic of the type <code>*(2darr + (row x nCols) + col)</code> shouldn't be guaranteed to work at all.</p>