[C] Detailed explanation of pointers (an article takes you to play with pointers)

Many people are having a headache for pointers when learning C language. Today's article will take you to play with pointers.

What are pointers?

In computer science, a pointer is an object in a programming language whose value points directly to a value stored elsewhere in the computer's memory, using an address. Since the required variable unit can be found through the address, it can be said that the address points to the variable unit. Therefore, what visualizes the address is called a "pointer". It means that the memory unit with its address can be found through it.
Considering comprehensively, our predecessors defined the size of a memory unit as a byte.
Each memory unit corresponds to a number, and we can find this piece of memory through this number, so how is the number generated?
Numbering is generated by electronic signals. We have 32 address lines under 32-bit machines, and 64 address lines under 64-bit machines. Let’s take 32-bit machines as an example. Each address line can generate 0/1 binary digits , so 32 address lines have 2 to the 32nd power number, that is, 2 to the 32th power of memory bytes, 4 GB of memory. To store these 32 bits, 4 bytes of memory are required, so under a 32-bit machine, no matter what the size of the pointer is, it is 4 bytes. By analogy, if there are 64 address lines on a 64-bit machine, the size of a pointer variable is 8 bytes to store an address.
in conclusion:

Pointers are used to store addresses, and addresses uniquely identify an address space.
The pointer size is 4 bytes on 32-bit platforms and 8 bytes on 64-bit platforms.

Pointers and Pointer Types

The pointer is typed, the address of the integer data should be placed in the integer pointer, and the address of the character should be placed in the character pointer. So what are the pointer types?
insert image description here
Here we can see that the way to define a pointer is

type name* name

The size of the pointer is the same under the same platform, so what is the use of the pointer type?

Pointer addition and subtraction integer

Code demo:

#include <stdio.h>

int main()
{
    
    
	 int n = 10;
	 char *pc = (char*)&n;
	 int *pi = &n;
	 
	 printf("%p\n", &n);
	 printf("%p\n", pc);
	 printf("%p\n", pc+1);
	 printf("%p\n", pi);
	 printf("%p\n", pi+1);
	 return  0;
}

Running results:
insert image description here
The addresses here are all expressed in hexadecimal. We can see that pc plus one skipped 1 byte, and pi plus one skipped 4 bytes, so the pointer type determines the pointer plus and minus integer The number of bytes to skip.
Summarize:

The type of pointer determines how far (distance) the pointer takes one step forward or backward.

pointer dereferencing

Dereferencing is to access the pointed content through the pointer, just add * before the pointer variable.
Code demo:

#include <stdio.h>

int main()
{
    
    
	 int n = 0x11223344;
	 char *pc = (char *)&n;
	 int *pi = &n;
	 *pc = 0;   
	 *pi = 0;   
	
	 return 0;
}

After executing *pc = 0, n becomes.
insert image description here
After executing pi = 0, n becomes.
insert image description here
We can see that the number of bytes dereferenced and accessed by different pointer types is also different.
Summarize

The type of the pointer determines how much authority (how many bytes can be manipulated) when dereferencing the pointer. For example: dereferencing a char* pointer can only access one byte, while dereferencing an int* pointer can access four bytes.

wild pointer

Concept: A wild pointer means that the location pointed by the pointer is unknown (random, incorrect, and without clear restrictions). If the pointer variable is not initialized at the time of definition, its value is random, and the value of the pointer variable is that of other variables. The address means that the pointer points to a variable whose address is uncertain. To dereference at this time is to access an uncertain address, so the result is unknown.
The wild pointer is very dangerous, it points to an indeterminate space, and accesses memory illegally.

Cause of Wild Pointers

1. The pointer is not initialized
2. Out-of-bounds access of the pointer
3. The space pointed to by the pointer is released

How to avoid wild pointers

  1. Pointer initialization (uncertainty is initialized to NULL first)
  2. Careful pointer out of bounds
  3. The pointer points to the space to release even if it is set to NULL
  4. Check the validity of the pointer before using it

The relationship between pointers and arrays

What is the name of the array?

Let's look at the following code

#include <stdio.h>
int main()
{
    
    
	int arr[10] = {
    
     0,1,2,3,4,5,6,7,8,9 };
	printf("%p\n",arr);
	printf("%p\n", &arr[0]);
	return 0;
}

Running result:
insert image description here
We can see that the array name is the address of the first element. Then we can put the array name in a pointer, and we can access the array through this pointer.
For example:

#include <stdio.h>
int main()
{
    
    
	 int arr[] = {
    
     1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	 int *p = arr; //指针存放数组首元素的地址
	
	 int sz = sizeof(arr) / sizeof(arr[0]);
	 int i = 0;
	 for (i = 0; i<sz; i++)
	 {
    
    
		 printf("%d ", *(p + i))// 这里的*(p+i)==p[i]
	 }
	 return 0;
}

secondary pointer

What is a secondary pointer?

A pointer variable is also a variable, and a variable has an address, and the secondary pointer is used to store the address of the pointer variable.
![Insert picture description here](https://img-blog.csdnimg.cn/1c26f7c8930640deab1203d1982ba099.png#pic_center

Arithmetic with Secondary Pointers

insert image description here
The ppa here is a secondary pointer.
*ppa finds pa by dereferencing the address in ppa, and *ppa actually accesses pa. **ppa first finds pa
through *ppa, and then dereferences pa: *pa, then the found is a.

character pointer

The character pointer is char*, we generally use it to store the address of the character. But there is another usage:

int main()
{
    
    
    char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
    printf("%s\n", pstr);
    return 0;
}

Here is to put the address of the first character of this string into pstr.
Let's look at the following piece of code:

#include <stdio.h>

int main()
{
    
    
	char str1[] = "hello world.";
	char str2[] = "hello world.";
	char* str3 = "hello world.";
	char* str4 = "hello world.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else

		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else

		printf("str3 and str4 are not same\n");

	return 0;
}

Let's analyze it first. We have created two arrays. The contents stored in the two arrays are the same, but the addresses of the two arrays must be different, so the first one must be not same, and the latter pointer variable, Both point to the address of the first element h of "hello world.", so they must be the same, so the second must be same. Let's take a look at the results:
insert image description here

Sure enough, the answer was the same as we thought.

array of pointers and pointer to array

array of pointers

As the name suggests, an array of pointers must be an array, but each element in the array is a pointer, for example:

int* arr1[10]; //Array of integer pointers

char *arr2[4]; //Array of first-level character pointers

char **arr3[5];//Array of secondary character pointers

Here we can use an array of pointers to simulate a two-dimensional array:

#include <stdio.h>

int main()
{
    
    
	int arr1[] = {
    
     1,2,3,4,5 };
	int arr2[] = {
    
     2,3,4,5,6 };
	int arr3[] = {
    
     3,4,5,6,7 };
	int* Arr[] = {
    
     arr1,arr2,arr3 };
	return 0;
}

Arr here is similar to a two-dimensional array, but the data of the two-dimensional array is stored continuously, and arr1 and arr2 here are discontinuous.

ArrayName and &ArrayName

Let's look at the following piece of code first:

#include <stdio.h>

int main()
{
    
    
	 int arr[10] = {
    
     0 };
	 printf("arr = %p\n", arr);
	 printf("&arr= %p\n", &arr);
	 printf("arr+1 = %p\n", arr+1);
	 printf("&arr+1= %p\n", &arr+1);
	 return 0;
}

operation result:

insert image description here
Here we can see that the address represented by the array name and the & array name are the same, both are the address of the first element, but the array name plus one skips the size of an element type, while the & array name skips the entire array size, that's the difference between them.

array pointer

Array pointers are, as the name implies, pointers. It points to the entire array and stores the address of the array.

int ( p2)[10]; (p2 is an array pointer)
The priority of [] is higher than
number, so () must be added to ensure that p is combined first.
P is first
combined with p, indicating that p is a pointer variable, and then it points to an array of 10 integers. So p is a
pointer pointing to an array, called array pointer.

Use of array pointers

Array pointers are generally used when passing parameters with two-dimensional arrays, for example:

#include <stdio.h>

void print(int(*p)[5], int x, int y) //这里的int(*p)[5] 也可以写成int p[][5]
{
    
    
	for (int i = 0; i < x; i++)
	{
    
    
		for (int j = 0; j < y; j++)
		{
    
    
			printf("%d ", p[i][j]);
		}
		printf("\n");
	}
}
int main()
{
    
    
	int arr[3][5] = {
    
     0 };
	print(arr,3,5);
	return 0;
}

What we pass here is arr, arr is a two-dimensional array, the first element is an array of int [5], and its address needs to be received by an array pointer.

function pointers and arrays of function pointers

function pointer

A function pointer is also a pointer, it points to a function, and the function also has an address, and the function pointer is used to store the address of the function.
Let's look at the following piece of code:

#include <stdio.h>

void test()
{
    
    
	 printf("hehe\n");
}

int main()
{
    
    
	 printf("%p\n", test);
	 printf("%p\n", &test);
	 return 0;
}

Running result:
insert image description here
We can see that the function name and & function name are both addresses of the function.
So how to express the function pointer?

void ( pfun1) ();
pfun1 is combined with pfun1 first
, indicating that pfun1 is a pointer, the pointer points to a function, the pointed function has no parameters, and the return value type is void.

As long as we know the return type of the function and the parameters, we can create a function pointer.

array of function pointers

To store the address of a function in an array, this array is called an array of function pointers. How to define an array of function pointers?

int ( parr1[10]])();
Parr1 is first combined with [], indicating that parr1 is an array, what is the content of the array?

is a function pointer of type int ( )() .

Purpose of function pointer: transfer table

That's all for today's sharing, thank you for your attention and support!

Guess you like

Origin blog.csdn.net/bushibrnxiaohaij/article/details/131601535