Understand in one article, pointer constants and constant pointers, pointer arrays and array pointers, pointer functions and function pointers

Foreword

Recently, I learned some knowledge about pointers in C++ and C language. After learning about pointers, I discovered that all kinds of monsters and monsters have appeared. Some commonly used knowledge can no longer be understood as long as it is combined with pointers, especially commonly used constants, arrays and function, so it took me a long time to make a summary. If there are any shortcomings, please give me your advice.

Text

First, you need to understand a precedence order: () > [] > * . There is crucial to understanding the relationship between arrays and functions and pointers.

Pointer constants and constant pointers

Pointer constant —- pointer type constant

Type name * const pointer name 

Definition: It is actually a pointer type constant, which is essentially a constant. Therefore, the address pointed to by the constant p cannot be changed (the address is a constant), which means that the value of the pointer cannot be changed, because the value of the pointer cannot be changed. It’s the address. The same address can have different values, so the value after *p dereference can be changed because it is no longer the address value.

Code example:

int a = 10,b = 20;
int * const p = & amp;a // constant must be initialized
p = & amp;b; // Error, address cannot be changed
*p = 30; // Correct, the value can be changed

Constant pointer —- pointer of constant type

Two ways of expression:
1. const type name * pointer name
2. Type name const * pointer name 

Definition: This refers to a constant pointer, that is to say, it is essentially a pointer.The pointer p defined here points to a constant (the value is a constant), so *p dereference is actually a constant. No changes can be made. The same value can have different addresses, sop is actually the value of a pointer, that is, the address, which can be changed.

Code example:

int a = 10,b = 20;
const int * p = & amp;a; / int const *p = & amp;a; // Constant must be initialized
p = & amp;b; // Correct, the address can be changed
*p = 30; // Error, value cannot be changed

Notes —- Pointers and string constants

Only simple numerical constants are used in the above. After understanding the relationship with pointers, we can know that for pointer constants, the value of the pointer after dereference can be changed,because in memory management, numerical constants Mainly stored in the data segment, or stackso it can be modified.

However, for string constants, it is allocated in the read-only storage area of the code segment. Usually this memory area is used for read-only and cannot be modified at will. Therefore, although the value in the pointer numeric constant can be modified, for the pointer string constant, str points to the first address of the string constant “Hello World”, and *str is the first character “H”, but the character Constants cannot be modified. In addition,the address of the pointer cannot be changed, because the pointer here is a constant and the address value cannot be modified.

Code example:

int main()
{
    char * const str = "Hello World"; // defines a string constant of pointer type
    * str = "Hello Earth"; // Error, the value of the string cannot be modified
    str = "Hello Earth"; // Error, the value of the pointer cannot be modified
    cout << str << endl;
    
}

Pointer functions and function pointers

Pointer function —- pointer type function

Two functions are declared in the code below. The first one is an ordinary function declaration, and the return value is an int type; the second main difference is that a pointer ” * ” symbol is added, that is, the return value is A pointer of type int is just an address. Therefore, when the two are used to receive return values, the int type variables defined are somewhat different.

Type name * function name (parameter list)

1. int fun(int a,int b);
2. int *fun(int a,int b);

Definition: A function of pointer type is essentially a function, but its return value is an address value, that is, it returns a pointer. Therefore, a pointer variable with the same type name must be used to receive this return value.

Code example:

struct Data
{
   int m_A;
   int m_B;
};

Data *fun(int & amp;a,int & amp;b)
{
   // Define a pointer of Data type to receive the return value of the pointer function
   Data *data = new Data;
   data->m_A = a;
   data->m_B = b;
   return data;
}

int main()
{
    // call pointer function
    Data * myData = fun(10,20);
    cout<<myData->m_A<<" "<<myData->m_B<<endl;
    delete myData;
}

Note: When calling a pointer function, a pointer of the same type must be used to receive the return value of this function.

Function pointer —- pointer of function type

Type name (*function name) (parameter list)

int (*pfun) (int a,int b);

Definition: A pointer of function type. The pointer points to a function. It is essentially a pointer. As can be seen from the previous priority, () has the highest priority. Therefore, the combination of the function name and the pointer * defines a pointer. The principle is that when a function is defined, the function name at this time is the first address of the function. Since the function name is also an address, a pointer variable can be defined to store it.

When using a function pointer, you need to assign the address of the function to the declared function pointer variable. Since a function name mentioned earlier represents the first address of the function, direct assignment is generally used.

//Define a function
int fun (int a, int b)
{
    return a*b;
}

Declare a function pointer
int (*pfun) (int a,int b);

pfun = fun; // pfun is a pointer that stores the function address, and fun is the name of a defined function.
              // It is also an address itself and can be directly equal.

Code example:

int Min (int x,int y)
{
     int z;
     if(x>y){
         z = y;
     }
     else{
         z = x;
     }
     return z;
}

int main()
{
    int (*pfun) (int x, int y);
    pfun = Min; // They are all addresses and can be directly equal.
    
    int a,b,c;
    cin>>a>>b;
    c = (*pfun)(a,b); // When calling a function, you can use a function pointer to call it. At this time, the dereferenced value is a value, not an address.
    cout<< "Min = "<<c<<endl;

    return 0;
}

Notes —- Function pointers and + +, — operations

We know that in ordinary numerical pointer variables, the pointer can be auto-incremented and self-decremented. Auto-increment (add 4 bytes backwards). In a 32-bit operating system, the left and right type pointers both occupy 4 byte), decrement in the opposite direction. However, since the function pointer points to a code segment, the size of each function is uncertain, so the step size of increment or decrement cannot be determined. That is to say, the function pointer pfun we declared in the code below cannot perform + + or — operations. If you need to perform this operation, you can define an integer variable to save the code name of each function, and then perform the function call operation.

void func1()
{
   cout << "This is func1." << endl;
}

void func2()
{
    cout << "This is func2." << endl;
}

void func3()
{
    cout << "This is func3." << endl;
}

int main()
{
    void (*pfun)() = func1; // Declare a function pointer
    int index = 1;

    // Increment the index of the function pointer
    index + + ;
    // Point the function pointer to the corresponding function
    if (index == 1)
    {
        pfunc = func1;
    }
    else if (index == 2)
    {
        pfunc = func2;
    }
    else if (index == 3)
    {
        pfunc = func3;
    }

    // Call the function pointed to by the function pointer
    pfunc();

    return 0;
}

Pointer array and array pointer

Pointer array —- array of pointer type

An array of pointer types is essentially an array. However, the elements in the array are all pointers, which actually means that the elements stored in the array are just addresses. If you need to operate this array, you must make the elements inside equal to the address.

Type name *array name [parameter];

int *arr [8]; // This defines an array with 8 int type elements, and the elements in the array are pointers

Code example:

int main()
{
int *pArr[4];
int Arr[4] = { 1,2,3,4 };
pArr[0] = & amp;Arr[0]; // Take the address of the first element in Arr and assign it to the first element of pArr
cout << pArr[0] << endl; // Output address 0071F8AC
cout << *pArr[0] << endl; // Output value 1
return 0;
}

Array pointer —- pointer of array type

Essentially a pointer. And this pointer points to an array. The elements in the array are still numerical values, but they are managed using a pointer.

Type name (*array name) [parameter];

int (*pArr) [8]; // A pointer is declared, and this pointer points to an array with 8 int elements

In the following example, a pointer is declared pointing to type int [4]. Then, we give the address of Arr to pArr, so that pArr points to the first row of the array. Next, we use + + pArr to point pArr to the next row of the array, and then use **( + + pArr) to access the first element of the row, which outputs 5.

Code example:

int main()
{
int Arr[3][4] = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
int (*pArr)[4];
pArr = Arr;
 cout << **( + + pArr)<< endl; // Output 5
system("pause");
return 0;
}

Summary

Different definitions

The essence of a pointer constant is a constant, the address is a constant, the address cannot be changed (& points cannot be changed), and the value can be changed.
The essence of a constant pointer is a pointer, the value is a constant, the value cannot be changed, and the address can be changed (the & amp; pointer can be changed).

A pointer function is essentially a function, but the return value is a pointer type. When using it, you must define a pointer variable of the same type to receive it.
A function pointer is essentially a pointer. Declaring a function pointer can assign the address of other functions to it. Use (*fun) to call a function

A pointer array is essentially an array. The elements in the array are pointers and occupy the storage space of multiple pointers.
The essence of an array pointer is a pointer. The pointer manages the elements of the array and occupies the storage space of a pointer in the memory.

If you want to make it easier to distinguish, you can also see that when I wrote, all the names that are essentially pointers have the pointer last, and the names that are essentially themselves have the pointer first.

Writing is different

Pointer constant:int * const p = & amp;a;

Constant pointer:const int * p = & amp;a; / int const * p = & amp;a;

Pointer function: int * fun(int a,int b);

Function pointer: int (*pfun) (int a,int b);

Pointer array: int *Arr[10];

Array pointer:int (*pArr)[10];