1 Basic Operations of Pointer Variables
int a,*iptr,*jptr,*kptr;iptr = &a;jptr = iptr;*jptr = 100;kptr = NULL;
Illustration:

1.1 Address and Memory Space
A pointer variable is also a variable that corresponds to a block of memory space and an address in memory; the name of the pointer is the address. How large is this empty memory space? It is one machine word long: for a 32-bit CPU and operating system, it is 32 bits, or 4 bytes, with a value range of: 0x-0xFFFFFFFF. For a 64-bit CPU and operating system, it is 64 bits, or 8 bytes, with a value range of: 0x-0xFFFFFFFFFFFFFFFF.
1.2 Value, Other Addresses, and Other Spaces
The value of a pointer variable is the address of the space it points to, and the size of the space at that address is determined by the type of the pointer variable.
1.3 Declaration and Initialization
When declaring a pointer variable without initialization, the pointer variable only acquires its own memory space, and its target is not yet determined. At this point, dereferencing the pointer variable as a left value is an illegal operation. If you want to use the pointer variable to dereference as a left value, there are three ways:
int *ptr;int *ptr_2;int a = 1; ptr_2 = &a;// *ptr = 0; // Illegal operation, its target memory space is not yet determined ptr = &a; // ① Right value is a variable address ptr = ptr_2; // ② Right value is a same-type pointer, and has been initialized ptr = (int*)malloc(sizeof(int));// ③ Right value is a memory allocation function returning a void pointer *ptr = 0; // Legal operation, ptr has a determined target and target memory space;
1.4 Passing Pointer Values Between Functions
In the function (as in the example funcForSpace()), local variables (like a in the example) are stored on a function’s stack frame. When one function finishes executing, another function (like stackFrame_reuse() in the example) executes, and that space will be reused by stackFrame_reuse(), meaning the space used by a will no longer exist. Therefore, when a pointer variable points to the memory space of a local variable, the address value passed to the calling function is not a valid value.
#include<stdio.h>
void funcForSpace(int **iptr){int a = 10; *iptr = &a;}
void stackFrame_reuse(){int a[1024] = {0};}
int main(){int *pNew; funcForSpace(&pNew);printf("%d\n",*pNew); // 10, at this point the stack frame has not yet been reused stackFrame_reuse();printf("%d\n",*pNew); // -858993460, garbage value while(1);return 0;}
You can allocate a block of heap memory in funcForSpace() and pass it to the calling function.
#include<stdio.h>
#include<malloc.h>
int g(int **iptr){ // When trying to modify the first-level pointer variable of the calling function, the parameter of the called function is a second-level pointer
if ((*iptr = (int *)malloc(sizeof(int))) == NULL)return -1;}
int main(){int *jptr; g(&jptr); *jptr = 10;printf("%d\n",*jptr); // 10free(jptr);while(1);return 0;}
The following illustration shows the pointer passing process of the above code:
In the following illustration, a represents computer memory, and b represents the stack frame space opened during a function call:
2 Pointer Variables and Array Names
In certain contexts, an array name will convert to the address of the first element of the array, facilitating pointer arithmetic, such as
#include<stdio.h>
int main(){int a[5] = {0}; char b[20] = {0}; *(a+3) = 10; // a+3 refers to the address a, offset by sizeof(int) bytes *(b+3) = 'x'; // b+3 refers to the address b, offset by sizeof(char) bytes
printf("%d, %c\n",a[3],b[3]); // 10, xwhile(1);return 0;}
The following illustration shows the pointer offset details of the above code:

3 Pointer Passing Between Calling and Called Functions
Consider the following code:
#include<stdio.h>
void swap1(int x, int y){int tmp; tmp = x; x = y; y = tmp;}
void swap2(int *x, int *y){int tmp; tmp = *x; *x = *y; *y = tmp;}
void caller(){int a = 10;int b = 20; swap1(a,b);printf("%d %d\n",a,b); swap2(&a,&b);printf("%d %d\n",a,b);}
int main(){ caller();return 0;}
The above code can be understood with the following illustrations:
swap1 by value:
swap2 by address (pointer passing):
4 Arrays as Function Parameters
A two-dimensional array is an array of arrays, and an n-dimensional array is an array of (n-1)-dimensional arrays. Memory is a one-dimensional sequence of bytes; the so-called n-dimensional array is merely a logical representation, while its physical structure remains one-dimensional and linear.
The elements of an n-dimensional array are (n-1)-dimensional arrays. If a pointer points to an n-dimensional array, its pointer type must include the length information of (n-1) dimensions, and this is also true when used as a function parameter.
void g(int a[][2]){ // void g(int(*a)[2]){ is the same syntax a[2][0] = 5;}
void caller(){int a[3][2];int (*p)[2] = a; *(*(p+2)+0) = 7; // p=2 refers to the address p offset by sizeof(*p)printf("%d\n",a[2][0]); // 7 g(a);printf("%d\n",a[2][0]); // 5}
The following code can be understood with the following illustration:

References:Kyle Loudon “Mastering Algorithms with C”