Use index operator on second rank pointer

I am confused about the problem with pointer and array in C.

First, let's see a code snippet:

//case 1 int **a; a = (int **)malloc(sizeof(int*)*m); for(i = 0; i < m; i++) a[i] = (int *)malloc(sizeof(int)*n); //case 2 int b[m][n]; 

then we knew that the location of b in memory is as follows:

 b[0][0] b[0][1] ... ... b[m-1][n-1] 

and the memory location is in the following order:

 a \ _\| a[0] a[1] ... a[m-1] | | | | | \|/ | a[1][0] a[1][a] ... a[1][n-1] \|/ a[0][1] a[0][2] ... a[0][n-1] 

So my question is this: since a[0..m-1][0..n-1] is stored inconsistently in memory, why can we use the subscript operator [] on a ? In other words, why a[i][j] can get the correct element, just like b[i][j] do?

+6
source share
5 answers

The compiler processes each part of the expression separately. The main difference between a[i][j] and b[i][j] is that since a is a pointer to pointers to int , calculating the address for a[i] counts the number of pointers, but since b is an array of arrays int , address calculation for b[i] counts the number of arrays. C uses the type of each part of the expression to determine how to evaluate it.

The steps for interpreting a[i][j] are:

  • a is a pointer to a pointer to an int .
  • a[i] is defined as *(a + i) .
  • The sum of a+i represents i elements outside of which a points. Since a points to pointers to int , we count i pointers to int to determine the new address.
  • Since the sum is a pointer to a pointer to an int , applying * to it gives a pointer to an int .
  • a[i][j] is defined as *(a[i] + j) . We have already appreciated part a[i] .
  • The sum a[i] + j is the j elements beyond which a[i] points are. Since a[i] points to int objects, we compute j int objects to determine the new address.
  • Since this sum is a pointer to int , applying * to it, we get int .

The steps for interpreting b[i][j] are:

  • b is an array of arrays m n int .
  • Since b is an array, it is converted to a pointer to its first element, an array of n int .
  • b[i] is defined as *(b + i) .
  • The sum b + i represents i elements beyond which b indicates. Since b was converted to a pointer to n int arrays, we compute i arrays n int to determine the new address.
  • Since the sum is a pointer to an array of n int , applying * to it gives an array of n int .
  • Since this expression is another array, it is converted to a pointer to its first element, int .
  • b[i][j] is defined as *(b[i] + j) . We have already estimated part b[i] .
  • The sum b[i] + j represents j elements beyond which b[i] indicates. Since it points to int , we compute j int to determine the new address.
  • Since this sum is a pointer to int , applying * to it, we get int .
+2
source

This is because a[i][j] is equal to *(*(a+i) + j) . Even if a not stored sequentially (possibly), the pointer *(a+i) will exactly point to the right place (where a[i][0] is stored).

+3
source

Since the elements of a are stored sequentially in memory, and the elements of each of a[n] are stored sequentially in memory. Executing int n = a[i][j] is basically equivalent to executing int * p = a[i]; int n = p[j]; int * p = a[i]; int n = p[j]; It does not matter that both measurements cannot be contiguous in memory for a in such a way that they are intended for b .

+2
source

They work because the compiler generates different for each case. Although it is true that the single sizes of arrays and pointers and similar ones, two-dimensionally sized arrays and pointers to pointers have similarities.

So, for case b , since the compiler knows that b is an array and is a sequential block of memory, it generates code like:

 // int c = b[i][j]; int c = *(b + (i*m+j); 

But it generates different code for a , since it is a pointer to a pointer, not a sequential block of memory. Each bracket operator is a dereference operator:

 // int c = a[i][j]; int c = *(*(a+i)+j); 
+2
source

For a[i][j]

We basically say:

We need the i'th pointer that a points to, and then we need the j'th int that this internal pointer points to.

Using only this concept, we can write

 foo(int **a, int rows, int cols){ //... //acess a[i][j] ; 0<=i<rows, 0<=j<cols } 
0
source

Source: https://habr.com/ru/post/954184/


All Articles