For example to understand the pointer pointing problem of two dimensional arrays in C language

  • 2020-05-07 20:04:23
  • OfStack

    didn't understand the concept of arrays very well before, except that the name of an array is just a constant pointer, which is similar to a basic pointer. So when I try to access a 2-dimensional array with a 2-level pointer, I often make an error. The following is the first written error of the program:


#include <stdio.h>

int main()
{
    int iArray[2][3] =    {{1,2,3},{4,5,6}};
    int **pArray = NULL;

    pArray = iArray;
    
    printf("array[0][0] = %d\n", pArray[0][0]);
    printf("array[1][2] = %d\n", pArray[1][2]);
        
    return 0;
}

At the beginning, I was like this analysis: the original array and pointer are similar, 1 - dimensional array and 1 - dimensional pointer, so the 2 - dimensional array name should be similar to the 2 - dimensional pointer, so the above program is not wrong, should print out 1 and 6. But when I actually compiled and ran, there was a segment error where I accessed the address space I wasn't supposed to. So what went wrong? How do you write the correct program?
To solve the problem,         had to make me understand arrays again. After perusing some books, I found that arrays are not as simple as I thought: a collection of 1 variables identified by 1 constant pointer. An array should also be a complete variable type: it has a name, a size, and an address. Just the name and the address. It's also because arrays have sizes that when you run the array name with sizeof, you get the size of the actual array, not the size of the pointer.
        because of this, the pointer to the array is not the same as the pointer to the pointer. The most obvious difference between the two is when the pointer steps. We know that the pointer in the + + operation, across the actual address depends on the pointer to the data type: for 1 a 32-bit machine, if point to, is int type data, across the physical address is 4, pointer to a data type, across the physical address is 4, when the point to an array type, across the physical address is the length of the array.
        now back to analysis the error above procedures, according to the operation rule of subscript reference symbol [], we know pArray [0] [0] is actually * * pArray, while iArray is actually an array variable names, and its value is the starting address of the array (actually & iArray, iArray, iArray [0] and & iArray values is the starting address of the array, is given by the compiler during compilation value). In fact, *pArray is already the value of iArray[0][0], which is 1, while **pArray is to access the data in the address space of address 1, which will naturally cause segment error.
        actually USES a pointer to access a 2-dimensional array and just USES a 1-level pointer. Take the following program:


int main()
{
    int iArray[2][3] =    {{1,2,3},{4,5,6}};
    int *pArray = NULL;

    pArray = iArray;
    
    printf("array[0][0] = %d\n", *pArray);
    printf("array[1][2] = %d\n", *(pArray + 1 * 3 + 2));
        
    return 0;
}

  because the array itself is sequentially arranged in the address space, based on the number of rows and columns, we can easily traverse all the data in the 2-dimensional array by calculating the address offset of the access cell by ourselves.
We can also try to access the members of a 2-dimensional array with Pointers to the array. Here is the story procedure:


int main()
{
    int iArray[2][3] =    {{1,2,3},{4,5,6}};
    int (*pArray)[3] = NULL;

    pArray = iArray;
    
    printf("array[0][0] = %d\n", pArray[0][0]);
    printf("array[1][2] = %d\n", pArray[1][2]);
        
    return 0;
}

We know that the [] operator is combined from left to right, pArray[1][2] is equivalent to (* (pArray + 1))[2], and since pArray is a pointer to an array and the length of the array is 3, * (pArray + 1) is equivalent to iArray[1], pArray[1][2] is equivalent to iArray[1][2].
        if we have to use a level 2 pointer to access a 2-dimensional array, we will have to borrow the pointer array (which stores data of pointer type). Here is the example program:


int main()
{
    int iArray[2][3] =    {{1,2,3},{4,5,6}};
    int *ipArray[2] = {iArray[0], iArray[1]};
    int **pArray = NULL;

    pArray = ipArray;
    
    printf("array[0][0] = %d\n", pArray[0][0]);
    printf("array[1][2] = %d\n", pArray[1][2]);
        
    return 0;
}

    since the level 2 pointer jumps twice, there is an extra space in between to store the level 1 pointer. So level 2 Pointers are generally not recommended for accessing 2-dimensional arrays.

As we all know, Pointers are really addresses! The address of a variable is called a "pointer" to that variable. If there is such a variable: its storage location is the location of other variables! Let's call it a pointer variable. (note the difference between the two: two completely different concepts!)
As we all know, the array name and the function name are their entry addresses. Similarly, a variable name is also the address of the variable! There is one type of operator in C: the address operator. Because array names and function names themselves represent addresses, they are not and cannot be addressed or otherwise manipulated (a direct reference to a function name is equivalent to addressing it). That's why they're called "constants"! But for one variable, it's a different story. To get its address, you have to do an ampersand, even though it represents the address value itself! The direct reference to the variable is the data content of the memory unit in which it is located! "Pointer variable" as a variable of course can not be an exception! The only difference between it and other ordinary variables is that its contents are the addresses of other variables (including "pointer variables"), and its size is always 32 bits on WIN32, 4BYTE. Ordinary variables have no size limit! The data content of the address to which the pointer variable points is obtained by the operator "*". In our understanding, we consider the "fetch operator *" as part 1 of a type, and this data type is a variable address type (for each "*")!
As long as understand the above common sense, "pointer" will no longer be in the program design "block"!
From the perspective of memory storage mapping, C regular arrays (not including multidimensional arrays designed through data structures) do not have multidimensional, which means that all arrays are essentially 1-dimensional, and 1-level Pointers are equivalent to 1-dimensional arrays! The key difference is the semantic difference between multidimensional arrays and 1-dimensional arrays! We understand that multidimensional arrays are often described graphically as "matrices". A more precise understanding is that each element of a multidimensional array is an array, and so on recursively until each element is a simple variable type, and you end up with a special 1-dimensional array!


Related articles: