Illustration of C Language Pointer Variables

1 Basic Operations of Pointer Variables

int a,*iptr,*jptr,*kptr;iptr = &a;jptr = iptr;*jptr = 100;kptr = NULL;

Illustration:

Illustration of C Language Pointer Variables

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:Illustration of C Language Pointer Variables In the following illustration, a represents computer memory, and b represents the stack frame space opened during a function call:Illustration of C Language Pointer Variables

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:

Illustration of C Language Pointer Variables

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:

Illustration of C Language Pointer Variables swap2 by address (pointer passing):Illustration of C Language Pointer Variables

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:

Illustration of C Language Pointer Variables

References:Kyle Loudon “Mastering Algorithms with C”

Leave a Comment