One-dimensional pointers, two-dimensional pointers and three-dimensional pointers in C language

A pointer can point to a common type of data, such as int, double, char, etc., or it can point to a pointer type of data, such as int *, double *, char * etc.

If a pointer points to another pointer, we call it a secondary pointer, or a pointer to a pointer.

Suppose there is a variable a of type int, p1 is a pointer variable pointing to a, and p2 is a pointer variable pointing to p1. Their relationship is As shown below:

Translate this relationship into C code:

int a =100;
int *p1 = & amp;a;
int **p2 = & amp;p1;

A pointer variable is also a type of variable and will also occupy storage space. You can also use & amp; to obtain its address. C language does not limit the number of pointer levels. For each additional level of pointer, an asterisk * must be added when defining the pointer variable. p1 is a first-level pointer, pointing to common type data, and has a * when defined; p2 is a second-level pointer, pointing to a first-level pointerp1, there are two * when defined.

If we want to define a third-level pointer p3 to point to p2, then we can write like this:

int ***p3 = & amp;p2;

The fourth-level pointer is similar:

int ****p4 = & amp;p3;

When you want to get the data pointed to by the pointer, add one * to the first-level pointer, add two * to the second-level pointer, and add three * to the third-level pointer. code>, and so on, please see the code:

#include <stdio.h>
int main(){<!-- -->
    int a =100;
    int *p1 = & amp;a;
    int **p2 = & amp;p1;
    int ***p3 = & amp;p2;
    printf("%d, %d, %d, %d\\
", a, *p1, **p2, ***p3);
    printf(" & amp;p2 = %#X, p3 = %#X\\
", & amp;p2, p3);
    printf(" & amp;p1 = %#X, p2 = %#X, *p3 = %#X\\
", & amp;p1, p2, *p3);
    printf(" & amp;a = %#X, p1 = %#X, *p2 = %#X, **p3 = %#X\\
", & amp;a, p1, *p2, * *p3);
    return 0;
}

operation result:

100, 100, 100, 100
 & amp;p2 = 0X28FF3C, p3 = 0X28FF3C
 & amp;p1 = 0X28FF40, p2 = 0X28FF40, *p3 = 0X28FF40
  & amp;a = 0X28FF44, p1 = 0X28FF44, *p2 = 0X28FF44, **p3 = 0X28FF44

*p3 gets the value of p2, which is the address of p1; *(*p3) gets is the value of p1, that is, the address of a; after three “value” operations, *(*(*p3)) gets is the value of a.

Pointer array

If all elements in an array hold pointers, then we call it an array of pointers. The definition form of pointer array is generally:

dataType *arrayName[length];

[ ] has a higher priority than *. The definition form should be understood as:
dataType *(arrayName[length]);

The brackets indicate that arrayName is an array containing length elements, and the brackets indicate that the type of each element is dataType *.

Except for the different data types of each element, pointer arrays and ordinary arrays are the same in other aspects. Here is a simple example:

#include <stdio.h>
int main(){<!-- -->
    int a = 16, b = 932, c = 100;
    //Define an array of pointers
    int *arr[3] = {<!-- --> & amp;a, & amp;b, & amp;c};//You can also write int *arr[] directly without specifying the length.
    //Define a pointer to an array of pointers
    int **parr = arr;
    printf("%d, %d, %d\\
", *arr[0], *arr[1], *arr[2]);
    printf("%d, %d, %d\\
", **(parr + 0), **(parr + 1), **(parr + 2));
    return 0;
}

operation result:

16, 932, 100
16, 932, 100

arr is a pointer array, which contains 3 elements. Each element is a pointer. When defining arr, we use the variables a, b, c The address initializes it, which is very similar to an ordinary array.

parr is a pointer to the array arr, specifically a pointer to the 0th element of arr. Its definition form should be understood as int *(*parr), the * in the brackets means that parr is a pointer, and the int * outside the brackets means The type of data pointed to by parr. The type of the 0th element of arr is int *, so two * must be added when defining parr.

In the first printf() statement, arr[i] means to obtain the value of the i element, which is a pointer. You need to add a * in front to get the data it points to, that is, in the form of *arr[i].

In the second printf() statement, parr + i represents the address of the i element, *(parr + i) means getting the value of the i element (the element is a pointer), **(parr + i) means getting the ith element The data pointed to by code> elements.

Pointer arrays can also be used in conjunction with string arrays, see the following example:

#include <stdio.h>
int main(){<!-- -->
    char *str[3] = {<!-- -->
        "c.biancheng.net",
        "C Language Chinese Network",
        "C Language"
    };
    printf("%s\\
%s\\
%s\\
", str[0], str[1], str[2]);
    return 0;
}

operation result:

c.biancheng.net
C language Chinese website
C Language

It should be noted that the character array str stores the first address of the string, not the string itself. The string itself is located in other memory areas and is separate from the character array.

Only when the type of each element in the pointer array is char *, you can assign a value to the pointer array as above, but not other types.

For ease of understanding, the above string array can be changed into the following form, they are all equivalent.

#include <stdio.h>
int main(){<!-- -->
    char *str0 = "c.biancheng.net";
    char *str1 = "C language Chinese website";
    char *str2 = "C Language";
    char *str[3] = {<!-- -->str0, str1, str2};
    printf("%s\\
%s\\
%s\\
", str[0], str[1], str[2]);
    return 0;
}

When it comes to multi-dimensional data structures, C language provides one-dimensional, two-dimensional and three-dimensional pointers to handle these data. A pointer is a special type of variable that stores a memory address and can be used to access and manipulate data in memory. This article will introduce the memory structure of one-dimensional pointers, two-dimensional pointers and three-dimensional pointers in C language in detail, and provide corresponding C language examples to deepen understanding.

One-dimensional pointer

One-dimensional pointers are an important tool for dealing with one-dimensional arrays. It stores the memory address of the first element of the array and can be used to iterate over the entire array. One-dimensional arrays are stored contiguously in memory, so a one-dimensional pointer can access each element of the array in sequence.

int arr[5] = {<!-- -->1, 2, 3, 4, 5};
int *ptr = arr; // Define a one-dimensional pointer and point to the first element of the array

for (int i = 0; i < 5; i + + ) {<!-- -->
    printf("%d ", *(ptr + i));
}

In the above example, we define an integer array arr containing 5 elements, and then define a one-dimensional pointer ptr pointing to arr . With the pointer ptr, we use pointer arithmetic to traverse the array and use the dereference operator * to access the value of each element.

Two-dimensional pointer

Two-dimensional pointers are used to process two-dimensional arrays, which store the memory address of each element of the two-dimensional array. Two-dimensional arrays are stored in memory in a row-major manner, that is, the elements of each row are stored consecutively. Two-dimensional pointers can access and manipulate the elements of a two-dimensional array through a pointer to each one-dimensional array.

int matrix[3][3] = {<!-- -->{<!-- -->1, 2, 3}, {<!-- -->4, 5, 6}, {<!-- -->7, 8, 9}};
int **ptr = (int **)malloc(3 * sizeof(int *));

for (int i = 0; i < 3; i + + ) {<!-- -->
    ptr[i] = matrix[i];
}

for (int i = 0; i < 3; i + + ) {<!-- -->
    for (int j = 0; j < 3; j + + ) {<!-- -->
        printf("%d ", *(*(ptr + i) + j));
    }
    printf("\\
");
}

free(ptr);

In the above example, we defined a two-dimensional integer array matrix containing 3 rows and 3 columns. Then, we use the two-dimensional pointer ptr to dynamically allocate the memory space of three pointers, and assign the first address of each row to the two-dimensional pointer. Through the two-dimensional pointer ptr, we use pointer arithmetic operations to access and operate on the elements of the two-dimensional array.

Three-dimensional pointer

Three-dimensional pointers are used to process three-dimensional arrays, which store the memory address of each element of the three-dimensional array. The storage method of three-dimensional arrays in memory is relatively complex, and it requires the use of multi-level pointers to represent it. Through multi-level pointers, we can access and operate elements of three-dimensional arrays.

int cube[2][2][2] = {<!-- -->{<!-- -->{<!-- -->1, 2}, {<!-- --> ->3, 4}}, {<!-- -->{<!-- -->5, 6}, {<!-- -->7, 8}}};
int ***ptr = (int ***)malloc(2 * sizeof(int **));

for (int i = 0; i < 2; i + + ) {<!-- -->
    ptr[i] = (int **)malloc(2 * sizeof(int *));
    for (int j = 0; j < 2; j + + ) {<!-- -->
        ptr[i][j] = (int *)malloc(2 * sizeof(int));
        for (int k = 0; k < 2; k + + ) {<!-- -->
            ptr[i][j][k] = cube[i][j][k];
        }
    }
}

for (int i = 0; i < 2; i + + ) {<!-- -->
    for (int j = 0; j < 2; j + + ) {<!-- -->
        for (int k = 0; k < 2; k + + ) {<!-- -->
            printf("%d ", *(*(*(ptr + i) + j) + k));
        }
        printf("\\
");
    }
    printf("\\
");
}

for (int i = 0; i < 2; i + + ) {<!-- -->
    for (int j = 0; j < 2; j + + ) {<!-- -->
        free(ptr[i][j]);
    }
    free(ptr[i]);
}
free(ptr);

In the above example, we defined a three-dimensional integer array cube containing two rows and two columns. Then, we use the three-dimensional pointer ptr to dynamically allocate the corresponding memory space, and assign the value of each element to the three-dimensional pointer. Through the three-dimensional pointer ptr, we use pointer arithmetic operations to access and operate on the elements of the three-dimensional array.