C Advanced Development Notes - Development Notes 29: Pointer and Array Analysis (Part 2)

--The difficulty of things is far less than the fear of things!

   In the previous article, we have made a simple analysis of pointers and arrays, so in this article, we will continue to analyze them in detail. First, let's ask a question:

   Array names can be used as constant pointers, so can pointers also be used as array names? In order to illustrate this problem, let's first take a look at the two access methods of the array. For the array int array[5] = {0}; the access methods are:

        - Subscript form: array[1] = 2;

        - Pointer form: *(array + 1) = 2;

    Comparison of two access methods:

        - The pointer moves in the array in fixed increments, which is more efficient than the subscript access form

        - It is more efficient when the pointer increment is 1 and the hardware has a hardware ah increment model

        -Conversion of pointer form and subscript subscript form:

                a[n] -> *(a + n) -> *(n + a) -> n[a]

    Although it is said that pointer access is more efficient than subscript access in theory, the optimization rate of modern compilers is quite high, and the efficiency of pointer and subscript access is already equivalent, but the subscript access form is more conducive to code readability performance and maintainability.

Knowing the two ways to access the array, let's take a look at the code below:

#include <stdio.h>

intmain()
{
    int a[5] = {0};
    int* p = a;
    int i = 0;
    
    for(i=0; i<5; i++)
    {
        p[i] = i + 1; //pointer to access
    }
    
    for(i=0; i<5; i++)
    {
        printf("a[%d] = %d\n", i, *(a + i)); //print array element value
    }
    
    printf("\n");
    
    for(i=0; i<5; i++)
    {
        i[a] = i + 10;
    }
    
    for(i=0; i<5; i++)
    {
        printf("p[%d] = %d\n", i, p[i]);
    }
    
    return 0;
}

The output result of the execution is that, from the output result, the array can indeed be accessed through pointers and subscripts:


        

    Let's take a look at a more error-prone and interesting knowledge point: For an array int array[5], what is the difference between array and &array?

        -array is the address of the first element of the array

        -&array is the address of the entire array

        The value of -array is the same as &array, but the meaning is different. The main difference is their pointer operation

            -array + 1 -> (unsigned int)a + sizeof(*a)

            -&array + 1 -> (unsigned int)(&a) + sizeof(*&a) -> (unsigned int)(&a) + sizeof(a)

            

In order to better understand the above content, the following is a piece of code to show:

#include <stdio.h>

intmain()
{
    int a[5] = {1, 2, 3, 4, 5};
    int* p1 = (int*)(&a + 1);
    int* p2 = (int*)((int)a + 1);
    int* p3 = (int*)(a + 1);
    
    printf("%d, %d, %d\n", p1[-1], p2[0], p3[1]);
    
    return 0;
}
//The above code, the output below is correct?
// A. The subscript of the array cannot be negative, the program cannot run
// B. p1[-1] will output a random number, p2[0] will output 2, and p3[1] will output 3
// C. p1[-1] will output garbled characters, p2[0] and p3[1] will output 2

Next, let's compile and execute:


From the output results, it seems that none of the three options match. Let's analyze them one by one:

    - The first output: Since we assign &a + 1 to the p1 pointer, the p1 pointer points to the end of the array, so does p[-1] -> *(p-1) point to the previous array element Woolen cloth? That is the element with the value of 5. That's right, that's it. Do you understand now?

    - The second output: the array name a represents the address of the first element, but we do (int)a + 1, which is actually converting the address of the first element into an ordinary integer. The ordinary integer is added by 1, which is very ordinary If a = 0xaabbccd0, then (int)a + 1 -> 0xaabbccd1, use this value as the memory address to take the value, and the obtained value must be random numbers or garbled characters.

    - The third output: This is easier to understand, p3 points to the array element a[1], p3 + 1 points to the array element a[2], and the resulting value is 3.


Now let's talk about array parameters

    - When an array is used as a function parameter, the compiler compiles it into a corresponding pointer

        void fun(int a[]) -> void fun(int *a)

        void fun(int a[5]) -> void fun(int *a)

That is, when an array is used as a function parameter, the function does not know the size of the array, so in general, when the function passes the array parameter, another parameter needs to be defined to indicate the size of the array.


Summarize:

    -Array names and pointers can only be used interchangeably, array names are not pointers, and pointers are not arrays in nature

    - The array name is the address of the first element of the array, not the address of the array

    - the array parameter of the function degenerates to a pointer

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325640166&siteId=291194637