Learning at Station B - 4 hours to thoroughly master C pointers - top programmers explain pointers with graphics and texts (mycoderschool-Points) - study notes sharing

foreword

This is the pointer teaching video of mycodeSchool of station B that I have studied before. This article is an article recorded while learning. Personally, I feel that it is super good. The teaching of pointers is really simple. I highly recommend everyone to learn. Below is a video link

Learning video link: https://www.bilibili.com/video/BV1bo4y1Z7xf/?spm_id_from=333.337.search-card.all.click&vd_source=33fb97de2a9fae8bce351df45c7d3074


article introduction

I take notes and study by each P. You can refer to each P of station B and watch it against my notes. For example, if you study the 1p, then you can check 01p

noticed
I took notes in Yuque and uploaded them to CSDN. Some of them are in the wrong format. If you want a PDF version, you can leave your email. That one looks better and the format is correct.


Basic introduction of 01p pointer

To understand pointers, we must first understand how different data types or different variables are stored in the computer's memory ?

The computer's memory (RAM random access memory)
segment or area, each represented by a byte in memory, as a typical memory system, each byte has an address

When a variable is declared in the program, such as int a, define an integer variable a

When this program is executed, the computer will allocate some memory space for this specific variable. How much memory space is allocated depends on the data type and also depends on the editor.

The computer will have an internal structure, a lookup table, which stores the information of the variable a

int a;
char c;
a++;

image.png
image.png

A pointer is a variable that holds the address of another variable

For example, there is a piece of memory with 4 bytes, starting from address 204 to store variable a, and another variable p, whose type is a pointer to an integer variable, this variable p can store the address of variable a

int a;
int *p;  //一个指针变量,指向一个整型,换句话说是指向整型变量的地址的变量

In order to store the address of a in p, we need

p = &a; 
//取a的地址  把&放在变量的前面就得到了这个变量的地址 
//实际上返回一个指针,指向哪个指定的变量

image.png

int a;		//a所分配的地址为204
int *p;		//p所分配的地址为64
p = &a;		//取a的地址
a = 5;		
printf p;	//204
printf &a;	//204
printf &p;	//64

image.png

If you put a * in front of the pointer variable, you will get the value of the address pointed to by the pointer. Call it dereferencing.

printf *p;   //5  = a的值
//在p中存放着一个地址,使用解引用操作来获得这个地址中的值
*p = 8;  //相当于修改了变量a的值,因为修改了p指向的值,而p又是指向a的地址
printf *p;  //8
printf a;	//8

When speaking of pointer variables, the value of the variable p refers to the address of the variable p

So * p is an address, p is a value , and this value is the value of the memory pointed to by the address stored in p.
image.png

Summarize

  1. define a pointer variable

int p; //put in front of the variable name

  1. pointer dereferencing

int p= &a; //Put & in front of the variable name to get the address of a

  1. When printing pointer variables

Do not use *, or do not use * to operate on it, all operations are to operate on its address

When using *, when operating on it, it is manipulating the value (content) of the address pointed to by the pointer


02p pointer code example

A pointer is a variable that is used to store the address of other variables.
The pointer can also point to a user-defined structure, or to a user-defined class
image.png

Example 1
The pointer p is not initialized, and the pointer p is used, an error occurs, and a problem occurs in the compilation phase.
the wild pointer problem
image.png

Example 2
The pointer p is initialized, pointing to the variable a
. Every time the program is re-executed, the address of p will be different, and a new address will be assigned to him.
The reason why *p is a negative value is because the variable a pointed to by p is not initialized, * some random value for p
image.png

Example 3
After initializing a, the value of *p is 10
image.png

Example 4
image.png

Example 5
Use a pointer to modify the value of a
image.png

Example 6

When the value of b is assigned to *p, will the pointer p point to b?

image.png

It can be seen that the pointer does not point to b, only the value changes, that is, the value of b is paid to *p, and the value of the address pointed to by the pointer to variable a is changed

image.png

Example 7
can initialize variables while defining variables

image.png

Example 8

Pointer p, adding and subtracting pointers, adding or subtracting is sizeof (variable), which will get the address of the next integer variable
For example: in the figure below, the size of an integer is 4 bytes, in order to get the next integer For the address of type number, 4 bytes will be skipped. So p+1 will add 4 bytes.

image.png

Example 9
p+1 points to a random value, which is actually a garbage value

We did not assign an integer variable to this particular memory address

So this operation is very dangerous and may access

image.png


03p pointer type, arithmetic operation, void pointer

Pointers are strongly typed , which means that a pointer variable of a specific type is required to store the address of a variable of a specific type

int * --> int
char --> char*

A pointer to an integer to store the address of the integer data
Pointer to a character type to store the address of the character data

If you have a user-defined structure or pointer, you need this specific type of pointer

We use pointers not only to store memory addresses, but also to dereference the contents of those addresses

In this way, the values ​​​​corresponding to these addresses can be accessed and modified.

Each byte can be addressed in memory, and the 4 bytes of an integer variable are generally arranged consecutively

The first bit is the sign bit, and the remaining 31 bits are used to store the value.
The float type refers to IEE-754. It is different from other types of stored data, and the printed value is also different.
image.png

Example 1
image.png

Example 2
p0 is a pointer to character type, and p is a pointer to integer type

Convert the forced type of p into a pointer to a character, and store the address of p into p0, then the address of the rightmost byte (that is, the first byte) will be stored into p0

You can see the running result of the program in the figure below. Since the char type is 1 byte, p0 stores the content of the first byte of the int type.
image.png
When dereferencing
p0, the machine will think it is a pointer to a character type, and the character type There is only one byte, so the machine only sees one byte
image.png

Example 3
p+1, jump to the position of the next integer variable, that is, the address plus sizeof (type), the size of the integer is 4 bytes, and p is a pointer to the integer, and *(p+ The value of 1) is a random value (garbage). We haven't written anything to this address.
image.png
p0+1 --> jump to the second byte of int type, get *(p0+1)=4 through binary
image.png


The address of the pointer p0 of the void type is the same as the address of p, but it is not mapped to a specific data type, and its address can only be printed out, but arithmetic operations cannot be performed on it, and a compilation error will occur
image.png

Summary :

pointer type, type conversion, pointer arithmetic

  1. What happens in memory when a pointer variable is dereferenced?

p=&a; p=(char ) p0;
is related to the address of the variable pointed to by the pointer and the type (byte size) of the variable.

  1. What happens when certain types of arithmetic operations are performed on pointers?

p+1; p0+1;
*(p+1); *(p0+1);

  1. A general pointer type, which does not target a specific data type, becomes a void type pointer

p0=p; there will be no compilation error
*p0; does not map to a specific data type, it cannot be dereferenced


04p pointer to pointer

Is it possible to create a pointer to a variable p (p is a pointer to an int)?
Create a pointer variable q, which is used to store the address of p; int **q;
so q is a pointer to a pointer

In this way, the address of p is stored in q, q points to p, and the type of q is **

The relationship here is that
in order to get the address of x, you need a pointer p of type int
. In order to get the address of p, you need a pointer to
type int, so add *, that is, int **

/******  地址对应内容
	x 地址-->225  内容 5
	p 地址-->215  内容 225
	q 地址-->205  内容 215
	r 地址-->230  内容 205
*********/

int x=5;		
int *p;			//p指向x  p的地址和x相同	
p = &x;
*p = 6;
int **q;  		//创建了一个指针变量q  指向p
q = &p;			//得到了p的地址 
int ***r;		//r的类型是int ***,因此可以用来存放int **类型的地址
r = &q;  

/******  解引用
	*p		6
	*q		225
	*(*q)   6
	*r		215
	*(*r)	225
	*(*(*r)) 6
*********/

image.png

Summarize

pointer, secondary pointer, tertiary pointer

int x;
int *p=&x;
int **q=&p;
int ***r=&q;

***p=**q=* r=x // Dereferencing is the same, both are equal to x

image.png


05p Function passing by value vs reference by value

The problem is introduced , the value is passed as a parameter, and the value of a cannot be changed

The reason is that a in InCrement is a local variable, and a in the main function is also a local variable. The a passed in by calling InCrement(a) in the main function is just a copy of a=10.

The a in InCrement has changed, but the a in the main function has not changed.
image.png
You can see that the address of a in the InCrement function is different from that in the main function

The one in the function is on the stack, and disappears after running. The one
in the main function exists in the heap. The auto-increment of the function has no effect on a in the heap.

image.png

What exactly happens in memory when the program starts running

When an application program starts, the computer will set up some memory to use
the code segment, static/global variable segment, and stack segment for this program. These three are fixed. When the program starts running, it has been determined. , but when the application is running, it can request to allocate more memory for it in the heap area

The memory used by the application program is usually divided into four parts .
The first part, the code segment
is used to store the instructions of the program. is a part in memory)
the second part, the static/global variable segment allocates static or global variables
(if we are not declaring the variable in a function, it is a global variable, and the global variable can be accessed and modified anywhere in the program) the third
part , stack (stack) very important
local variables are placed in this place
and local variables can only be accessed and modified in a specific function or a specific code block.
The fourth part, heap (heap)
image.png
before the program runs: code area, static/global Variable area, literal constant area
After the program runs: stack area (allocated automatically by the system) and heap area (applied by the programmer)
image.png
image.png

The detailed process of program running:
image.png
call stack or function call stack
If a function calls another function infinitely, just like infinite recursion, then the stack will overflow and the program will crash

Understand concepts or impressions, what happens when a function calls another function When a function is called
image.png
, it essentially maps one variable to another variable, and copies the value in one variable to another variable. Known as call by value
image.png

Solution:
pass address, you can refer to this variable, dereference and do some operations, this is call by reference (call by reference).
Passing by reference can save a lot of memory space
. Avoiding the copy of complex data types can save us memory
image.png


06p Pointers and arrays

The storage method of the array in the memory is
linear storage, the addresses of the elements in the array are linearly increasing . The value of the variable is unknown, and an error occurs
image.png


image.png

Solution
If the pointer p points to the address of the first element of the array
, and then execute p+1, p+2..., the dereference can be successful. Because the array is stored linearly in memory, we know what is in the adjacent address

int  A[5];
int *p;
p = &A[0];
print  P;   //200
print *p;   //2
print p+1;	//204
print *(p+1) //4

image.png

If we use the array A to be equal to the pointer p
, we still get a pointer to the first element of the array

int A[5];
int *p;
p=A;
print  A;   //200
print  p;	//200
print *A;  //2;
print A+1; //204
print *(A+1;  //4

So for the element whose index is i in the array, in order to get the address or value of this particular element

You can use
7
to get the address
&A[i] or A+i
to get the value
A[i] or *(A+i)
7

image.png

The first address of an array element can also be called the base address of the array, which
can be used

A or &A[0] indicates the first address of the array

image.png
image.png

Note
When the pointer points to the base address of the array, A++ cannot be executed
because A is essentially an array, and the first address of the array should remain unchanged and cannot be changed. Instead,
p++ can be executed because p is a pointer variable of type int
image.png

Summarize:

  1. The storage form of the array in memory

The address of the elements in the linear storage array is linearly increasing

  1. how to get address of array

Array name A or &A[0] to get the first address of the array
or use int *p=A; p also indicates the first address of the array

  1. How to access an array using a pointer

int *p =A;
*(A) //the first value of the array *(A+i) //the i-th value of the array
*p *(p+i)


07p Arrays as function arguments

The array is passed in as a function parameter

Get the number of arrays

int A[] = {1,2,3,4,5};
int ArraySize = sizeof(A)/sizeof(A[0]); //Number of elements in the array

The array is passed in as a function parameter
image.png

But when the parameter is passed in, only the array is passed, and
an error will appear as a result.
image.png
It can be seen that the array size of sizeof(A) is different in the sum function and the main function.
image.png

why?
The array A in the sum function is a local variable, not the array A in the main function.
When the function is called, the array A in the main function will be copied to the called function.
At the same time, the array in the stack frame of the main function in the stack A will occupy 20 bytes, and the array A copied to the sum function will also occupy 20 bytes. The elements in it are the same as the array A in the main function, but this is not the case
image.png

When the compiler sees the entire array A as a function parameter, it does not copy the entire array.
In fact, what the compiler does is create a pointer A with the same name in the SOE stack frame instead of creating the entire array.
The compiler just copies the main Call the address of the first element of the array of the function
, so the array parameter of SOE is not interpreted as an array, but an integer pointer
. This is why sizeof(A) is equal to 4 in the SOE function and an array in the main function.

We are not copying the value of the variable, but just copying the address of the variable , so here is a reference, not a value

Arrays are always passed to functions as references

If the entire array is copied every time, a lot of memory will be wasted

image.png

Therefore, when an array is used as a function parameter, it is essentially a pointer,
and the result is the same.
When an array is used as a function parameter, what is returned is essentially an array pointer, and the method is passed by reference.
image.png
image.png

Because the array is a function parameter, it is essentially a pointer, so the value of the array can be modified inside the function
Array name --> Pointer constant
image.png

Summarize

  1. When the main function calls the function, the array is used as the parameter of the function, and the process in the memory
  2. As a function parameter, an array is essentially equivalent to a pointer, but it is not a pointer. In fact, the first address of the array is passed instead of a copy of the entire array.
  3. How to find the number of elements in an array

size = sizeof(A)/sizeof(A[0])

  1. As a function parameter, the array is passed by reference , so the value of the array can be modified inside the function

08p pointer and character array (on)

The difference between a string and a character array
depends on whether there is \0 at the end
"hello" character array "hello\0" ​​string

The string must end with '\0' '\0' means NULL

The reason why character arrays are important is because we use them to store strings , and then do some operations, such as modifying, copying strings, concatenating two strings or finding out properties of strings (finding out the length of a string)

First understand
how to pass a string into a character array. Declare and initialize a character array. The first requirement is that the character array must be large enough. How big is the character array?

A sufficiently large character array whose size is greater than or equal to the number of characters + 1

The size of the character array >= the number of characters + 1

image.png

The size of the character array is too small,
if it does not end with \0, an error will appear
image.png

  1. When \0 is added to the last digit of the array, the output is successful

The printf function terminates the default last NUL character, that is, \0, the string termination symbol
image.png

In the string.h library, all functions assume that the string ends with \0.
For example, to find the length of a character array, the calculated length defaults to \0.
image.png

  1. You can assign values ​​to the elements of the character array individually or as a whole

For example:

char c[20]="JOHN";

This initializes the character
array c to a string and appends \0 which is implicit for string literals and always appends a NUL character at the end of memory

  1. You can also not specify the length of the character array

In this case the size of c will be 5, 5 bytes, one byte per character

char c[] = "JOHN";

But the length of the character array is 5
but the length is 4 because the strlen function does not count \0 (NUL character)
image.png

  1. You can also declare the character array explicitly, but the last character \0 must be declared explicitly

The size of the array must be greater than or equal to the number of characters in all
image.png

Note that it cannot be declared in the previous line and assigned in the next line, which is illegal
image.png

Arrays and pointers look similar, but are not the same type

char c1[6]="hello";
char *c2;
c2=c1;   //c1代表c1字符数组的首地址

print  c2[1]//数组的第二个元素  e
c2[0] = 'A';    //修改后c1就是 "AELLO"


c2[i]  -- > *(c2+i)   //c2是指向了c1的首地址  c2[i]就相当于c2+i的偏移
c1[i]  -- > *(c1+i) 

image.png

Notice

c1 = c2;   		//invallid
c1 = c1 + 1     //invalid
//invalid  因为c1是数组的首地址  数组的首地址不允许更改  会产生编译错误

c2 = c1;   //valid   
c2 = c2+1;   //c2指向下一个元素

You must understand when it is an array and when it is a pointer, the difference between the two, and what we can do respectively.

Example
Character array When the function parameter is passed in the address
%c, print characters
The string ends with \0
c[i] and *(c+i) are equivalent
image.png

The figure below can also print out character arrays.
Why?
The char C in the print function is like a pointer, pointing to the first address of the C[20] character array in the main function,
so the C in the print function
is equal to the c[0] C++ in the main function
, and the address is incremented, when the last character is \0, the loop terminates
image.png
the summary

  1. The difference between strings and character arrays

The string ends with \0 and
the character array is used to store the string

  1. Four initialization methods of string array

char c[] = “hello”;
char c[20] = “hello”
char c[20]; c1=‘h’; c2=‘e’;c3=‘l’; c4=‘l’; c5=‘o’; c6=‘\0’;
char c[] = {‘h’,‘e’,‘l’,‘l’,‘o’,‘\0’};

  1. The difference between %s and %c

%s print string %c print character

  1. Pointers and character arrays operate on character arrays using pointers

When an array is used as a function parameter, the first address of the array is passed by reference

  1. The difference between length and size

char c[20] = "hello";
size sizeof© -->6
length strlen© -->5


09p pointers and character arrays (below)

String constants and constant pointers

When writing a program, when executing a program, we should always be able to figure out where the variables are placed, or where the data is placed and where the
scope of the variable or data is placed

The stack is a continuous memory.
The stack area is used to store information during function execution and store all local variables.

When discussing pointers should know what happens in memory?
When any function is called, it will open up a space in the stack area to execute that function and become a stack frame.
The local variables of the stack
function will be allocated to the stack frame. In addition to the local variables, the stack frame has some other information

When a function is called, the called function will allocate a corresponding stack frame, which will be above the calling function main, the function on the top of the stack will be executed first, and the main function will suspend running (this can be regarded as an interruption).

Pointer variables, typically, the size occupies four bytes.
image.png
When the called function finishes running, the stack frame of the called function will be cleared.
The main function will resume running until the end.
image.png

Modify the code as follows.
What is defined is not a character array, but a character pointer

When an array of characters is used for initialization, the string will exist in the memory space allocated by the system to the array

In this case, it will be allocated on the stack

image.png

When a pointer is defined to point to a string , the string
is stored in
the code area of ​​the application

char *p = "helloworld" 1. Apply for a space (constant area), 2. Store a string 3. Add \0 after the string The returned address is assigned to the pointer p

This is stored in the code area, and modification is not allowed, which may cause the program to crash
:::
image.png

If modified, an error occurs
image.png

But when it is defined as a character array, you can modify
char *C to point to the first address of the character array c
, so it can be modified
image.png

When we define a function that allows reading but not writing,
we can define a pointer to a constant (read-only) character

const char *c;

When modifying, there will be an error
image.png
read-only, and it can work normally
image.png

Summarize

  1. When writing a program, when executing a program, we should always be able to figure out where to put variables, or where to put data and where to put the range of variables or data
  2. When discussing pointers should know what happens in memory?

Pointer variables, typically, the size occupies four bytes

  1. The character array is initialized and will be allocated on the stack

The character pointer is initialized and will be allocated to the code area (not writable)

  1. If you need a read-only function , you can define a pointer to a character constant

*const char c;

  1. Understand the relationship between pointers and arrays What happens to pointers in memory

The deep meaning of pointers as function parameters


10p pointers and two-dimensional arrays

  1. Pointers to manipulate one-dimensional arrays

int A[5];
int *p=A;
Just use the array name A, then in the expression, a pointer to the first element of the array will be returned
** You can use the array name as a pointer **
You can also use the array dereferencing and arithmetic operations on the name
, but it is different from the pointer variable (eg: p++ can be used but not A++, because the array name A is the base address of the array)

*(A+i) --> A[i];
A+i --> &A[i];

  1. Use pointers to manipulate two-dimensional arrays

The allocation of two-dimensional arrays in memory
B[0] and B[1] each have three elements ,
B[0] and B[1] are not an integer data, but a one-dimensional array with 3 integers

int B[2][3];
B[0]   B[1]   //每个都有三个整型数据

int *p = B;    //编译错误
//B返回的是一个指向一位数组(其中包含三个整型数据)的指针

image.png

The type of pointer is very important, when dereferencing and performing arithmetic operations on it , the results of different types of pointer operations are different

Define a pointer to a one-dimensional array (where the one-dimensional array contains 3 integers)

int (*p)[3] = B;   //这样赋值是可以的

print  B;   //和B[0]地址相同  B  --> &B[0]
print  *B;   //和B[0]的值相同,返回三个整型数据  也和B[0][0]的地址相同

B   -->  &B[0]   
*B  -->  B[0] (包含三个整型数据)   &B[0][0]
B[0]是存放三个整形数据的一维数组的名字  所以等同于 B[0][0]的首地址

image.png

print  B;      //400   B返回一个一维数组 包含三个整型
print  *B;	   //400
print  B+1;		//412
print *(B+1);	//412

image.png

image.png

image.png

Premise:
int B[2][3];
* int ( p)[3] = B; //B --> &B[0]

Conclusion: (think for yourself)
B = &B[0]
*B = B[0] = &B[0][0]
B+1 = &B[1]
* (B+1) = B[1] = &B[ 1][0];
*(B+1)+2 = B[1]+2 = &B[1][2];
*( B+1) = (B[0]+1) = *(&B[ 0][0]) = *(&B[0][1])

B here is a pointer to a one-dimensional array (with three elements)
B --> int (*)[3];
**B[0] --> int ***

Summarize:

  1. How two-dimensional pointers are stored in memory
  2. Use pointers to manipulate two-dimensional arrays

int B[2][3]; int (*p)[3]=B;
The type of the pointer is very important. When dereferencing and arithmetic operations are performed on the pointer, the results obtained by different pointer types are different

  1. B[i][j] = *(B[i]+j)= (B+i))

If you have time, you can watch more 10P


11P pointers and multidimensional arrays

Learned how to use pointers to operate on two-dimensional arrays,
how to operate on multidimensional arrays
, and how to pass multidimensional arrays as parameters to functions

It is important that multidimensional arrays are essentially arrays of arrays

An array can be understood as a collection of things of the same type

A multidimensional array can be understood as a collection of arrays

B[2][3] is a collection of one-dimensional arrays.
We have two one-dimensional arrays
, each of which has three integer elements
and they are allocated in contiguous memory.

B is a 2D array is an array of 1D arrays (of size 3)
so * B returns a pointer to a 1D array of 3 elements int( p) = B;

image.png

*B is the same as B[0], get a complete one-dimensional array B[0]
B[0] will return an integer pointer, pointing to the first element B[0][0] of B[0], That is, the address of B[0] is equal to B[0][0]
image.png

The role of the pointer type
works when dereferencing and performing pointer arithmetic

B[i][j] = *(B[i]+j) = ( (B+i)+j)
image.png
What is a pointer to a pointer and what is an array to an array? leave a suspense

  1. If there is a three-dimensional array C

int C[3][2][2];
int (*p)[2][2] = C;
is an array of two-dimensional arrays

image.png

Dereferencing
C returns a pointer to a two-dimensional array but is not essentially a pointer C itself is an array The two types are different
image.png

A batch of small conclusions
image.png
nice
image.png

Case
Think about it, matryoshka dolls, step by step, arrays of arrays
image.png
, every time you run, the memory allocated to the stack will change every time you run
image.png

  1. Multidimensional arrays passed to functions as function arguments

1D array as function argument
image.png

Two-dimensional array as a function parameter
The first definition method
image.png
The second definition method
image.png
**error **
image.png

Three-dimensional array as a function parameter
The first definition method
image.png
The second definition method
image.png

The same is true for an array of any dimension as a function parameter, except for the first dimension, the rest of the dimensions are mandatory to be given


12p pointers and dynamic memory stack vs heap

Understand
the architecture of memory,
how the operating system manages memory
, and how to manage memory as a programmer

Dynamic memory in c\c++

Code area (code area, stores instructions to be executed)
Static/global variable area (static/Global area) , stores static or global variables (global variables not declared in functions), the life cycle runs through the entire application program, in the application They can be accessed during the running of the program.
The stack (stack) is used to store all the information of the function call (functions Call) and all the local variables (local varibles). Survive during execution. Stack last in first out.
The size of these three areas will not grow during the running of the program

How are these three areas used during program execution?

the stack

**The stack frame size of a function is determined during compilation**During the
execution of the program, the function on the top of the stack is executed at any time, and other functions will be suspended (interrupted), waiting for the above function to return some Resume execution of nested function call after something
(nested interrupt)
image.png


When the called function ends, we will return to the interrupted place (that is, the place where the function is called), the stack frame of the previously called function will be eliminated (destroyed), and other functions will resume execution .
Until the end of the main function, the program terminates.
Finally global variables are also destroyed.

Usually only when a variable needs to be called by many functions, it must exist in the life cycle of the entire program, otherwise defining a global variable is a waste.

When the program starts to execute, the operating system allocates some memory.
Suppose the os allocates 1MB of memory as a stack, but the actual allocation of stack frames and local variables is at runtime.
If our stack grows beyond the size of the reserved memory.
It will generate stack overflow (stack overflow).
In this case, the program will error
eg: infinite recursion caused by writing a problematic recursive function.
image.png
Therefore, the stack is defective

The space reserved for the stack in memory will not grow during runtime, and the application cannot request more stacks during runtime

Assuming that 1mb is reserved, when the stack size allocated to variables and functions exceeds 1MB, the program will crash

There are certain rules for the allocation and destruction of memory on the stack.
When a function is called, it is pushed onto the stack. When the call ends, the stack is popped.
If the variable is allocated on the stack, the scope of the variable cannot be manipulated.

Another limitation, if we want to declare a large data type, such as a large array as a local variable, we need to know their size during compilation

If we need to determine the size of the array according to the parameters during the running of the program, there will be problems using the stack

heap

Solution:
For example, allocate a large amount of memory, or reserve variables in memory until we want to use it. At
this time, we need to use the heap (heap)

The heap of the application is not fixed, its size is variable throughout the life of the application , and there are no special rules for allocating and destroying corresponding memory , and the programmer can completely control it . For example, how much memory is allocated on the heap, and the memory on the heap can be used almost arbitrarily, as long as it does not exceed the memory limit of the system itself.
But using the heap indiscriminately is also very dangerous

Sometimes the heap is used as a free pool of memory (free store) or free memory area
We can get the memory we want from the heap

How the operating system implements the heap may be very different. This is a matter of the system architecture.
But from the perspective of the programmer, it is just a piece of memory that can be used freely, and the heap can be flexibly used according to needs. It is
also called Dynamic memory, using the heap means dynamic memory allocation

The heap is also a data structure, which has nothing to do with the heap in the data structure. The heap here is only used to represent the free memory pool

In order to use dynamic memory in the heap, we need four functions

/*-------------C语言:-------------------*/
malloc();
calloc();
realloc();
free();

/*-------------C++语言:-------------------*/

new();
delete();

image.png

Example 1, use C language to dynamically allocate memory
Allocate an integer in the heap, reserve or obtain some space on the heap, and use the malloc function
to allocate four bytes of memory on the heap
under the malloc function. bytes of memory

int *p;
p = (int*)malloc(sizeof(int));

When the malloc function is called, and the value passed in is an integer size
, malloc will apply and allocate 4 bytes of memory on the heap

Returns a pointer to the starting address of this memory
malloc returns a pointer of void type

For example, the starting address of returning 4 bytes is 200
malloc will return 200

p is a local variable of the main function and will be allocated in the stack frame of the main function.
Casting is used because malloc returns a pointer of type void

Now there is a piece of memory on the heap, which can be used to store an integer,
but I don’t know what is stored in the memory in the heap. You can use *p to dereference this address, and then write the value

The only way to use the memory on the heap is by referring to
the malloc function. The only thing it does is to find free memory on the heap, reserve space for you and then return it through a pointer.
The way to access this memory is to define a pointer yourself, through Dereference the way to access this memory
image.png

Example 2
calls malloc again. When malloc is used again,
it will allocate another memory on the heap, occupying four bytes.
Another address is allocated, and then let p point to
the memory allocated before this memory, which is still in the heap. On, the memory of the heap is consumed and will not be automatically recovered
image.png

If we use malloc to allocate and use a piece of memory on the heap, it must be released when it is used up, otherwise there will be a memory leak (wasting memory). Therefore, once the memory with the address of
200 in the heap is used, it must be passed free() function to release the memory

Any time the memory allocated by the malloc function will eventually be released by calling the free function
Use the free function to pass the memory start address to free
free(p pointer);

So in this way, the first piece of memory will be released, and then point to another piece of memory
. If the memory is allocated and no longer needs to be used, it must be released manually (the responsibility of the programmer)
image.png

So any memory allocated on the heap will not be automatically released like the stack after the function call ends.
Dynamically allocated memory needs to be released manually.

Dynamically allocated memory does not exist in the entire life cycle of the program like global variables, and the programmer can choose when to manually release the memory on the heap.

Example 3
If we want to allocate an array on the heap
, then as follows, we
only need to pass in the total size of the array in bytes

int *p = (int*)malloc(20*sizeof(int));   
//在堆上分配一个长度为20的整型数组空间
//堆上会分配一个连续的并且足够存放20个整型的内存
//会得到这块内存的首地址
//这样就可以使用了    p[1]   p1[2]
//*p = p[0]    //p  -->  &p[0]
//*(p+1) = p[1]

image.png

If malloc cannot find a free memory block, it cannot successfully allocate memory in the heap and returns NULL

Example 4: Using C++ to dynamically allocate memory
In C++, no type conversion is used, while in C malloc returns a void pointer. In
C++, new and delete are safe.
It means that they carry types and return pointers to specific type of pointer
image.png

Summarize:

  1. The difference between stack and heap

The stack is flawed . Improper operation of the stack will overflow the scope of variables in the stack and cannot be changed.

  1. How to allocate memory in the heap

The size of dynamically allocated memory is variable throughout the life of the application, and there are no special rules for allocating and destroying corresponding memory, which the programmer can fully control.

  1. Several functions about dynamic memory allocation

malloc() calloc() realloc() free() c language
new delete c++


13P pointer and dynamic memory malloc calloc realloc free

The concept of dynamically allocating memory
The meaning and difference of heap and stack in the application program

Various library functions in C language that support dynamic allocation of memory
image.png

malloc

Detailed malloc function is very detailed

void* malloc(size_t  size)

The size_t type is similar to (unsigned int)
size The byte size of the memory block is a positive integer
The size cannot be negative, it can be 0 and a positive number

Return a void pointer, which points to the address (first address) of the first byte allocated to our memory block in the heap.
Using malloc, you can allocate some memory, reserve some memory in memory, and
save some data in memory

In fact, when allocating memory, we will first calculate how much memory we need.
Usually, we will calculate the size returned by sizeof() * ​​the number of units required. The
total number of bytes required is: the number of units * the number of bytes per unit

int *p = (int *)malloc(sizeof(int))  //在堆上分配一个整型数据的内存空间
free(p);

p = malloc(int *)malloc(sizeof(int)*20) //分配连续的20个整型数据的空间

The size of the variable depends on the compiler, so malloc should be used to calculate the size of the type
image.png

How to fill data in the memory allocated to the heap
image.png
image.png

The operation of dynamic memory is based on pointers, which will return a base address pointing to the memory allocated in the heap

calloc

void* calloc(size_t num,size_t size)

The first parameter is the number of elements of a particular type and the second parameter is the size of the type

If you want to allocate space for three integer data in the heap

int *p = (int *)calloc(3,sizeof(int))

image.png

Both malloc and calloc can open up space in the heap area
The difference between malloc and calloc

Mallo will not initialize the memory after allocating it, so if the requested memory is not filled with data, some random values ​​will be used to
use calloc, which will initialize and assign the initial value, and the filling value is 0

realloc


Explanation of the usage of realloc function_Luv Lines Blog-CSDN Blog

void* realloc(void* Ptr,size_t size)

:::info
The first parameter Ptr refers to the pointer to the start address of the allocated memory The
second parameter size refers to the size of the new memory block
:::

The usage scenario of realloc

  1. The new memory block we want may be larger than the original one. In this case,

The machine will create a new piece of memory and copy the original value

  1. If there is contiguous memory available in the adjacent part of the previous memory

Then it may directly expand the previous memory

Example 1

Declare an array, but the array is what the user wants
If you don't declare the size of the array first, an error will occur

enter n;

int A[n];   //会编译错误  必须实现知道数组的大小 否则会erro 括号里的值不能是一个变量

You can use dynamic memory allocation
, so you have an array of size n
using malloc
image.png

Write data to the array and print the array
image.png
printout
image.png

use calloc function
image.png

The difference between calloc and malloc

If not initialized,
the array elements generated by the calloc function will be initialized to 0

image.png
But if you use malloc, the elements in the array will not be initialized, and there are some random values ​​in the array
image.png

Example 2

Any allocated dynamic memory will always exist (occupy memory) until the end of the program
unless explicitly released
memory allocated using malloc, calloc, realloc, use the free function to release memory
image.png

When free(A), the data in A will be cleared or may not be cleared, depending on the compiler or machine,
but after free(), that piece of memory can be allocated and used by another malloc. If there is no
random value
image.png
Free, print initialized 1, 2, 3, 4, 5
image.png

Although the memory is freed using free, we can still access that memory later, which is a dangerous place to use pointers

If you know the address, you can check the value stored in the address, but you should only read and write memory allocated by the system or allocated by yourself

If the address is not assigned to you, you don't know what is on the address you read and write, and you don't know what its behavior is, it all depends on the compiler and machine - is this a wild pointer?

After free, what will happen when accessing and assigning to the memory in the heap?
You can see that the value in the memory address has changed.
It depends on the compiler, and it may crash in other machines.
image.png

Only use the allocated memory, do not use other memory that does not belong to you.

Example 3

Suppose there is a piece of memory storing n integer data, and then we want to expand this piece of memory,
such as doubling or halving the size

Requirements: Double or halve the memory size
and use the realloc function

int *A = (int*)malloc(sizeof(int)*n);
free(A);

int B = (int*)realloc(A,2*nsizeof(int));   //内存大小翻倍
free(B);
    
int C = (int*)realloc(B,(n/2)*sizeof(int));  //内存减半
free(C);

Double the memory
and copy the content of the previous memory block into
it How it works : If the requested new block is larger than the previous block, if the previous block can be extended
If continuous memory can be found on the basis of the previous block, then expand previous block.
Otherwise, allocate new memory, copy the content of the previous block, and then release the previous memory
image.png

After using realloc to modify the size of the memory,
you can see that B still points to the first address of memory A

image.png
Input, print output, the current memory address is the same as the previous internal address, just expand the memory. The
first five elements copy the value of A,
and the last five elements are random values.
image.png

If you halve the size of the array
, the previous block will be reduced.
image.png
The first two elements are copied, not actually copied (they are already there), and the remaining three are freed.
image.png

if

int *A = (int*)malloc(sizeof(int)*n);
free(A);

int A = (int*)realloc(A,0);   /
free(B);

This is equivalent to the entire A array will be released
image.png

Most of the time, we will assign the address returned by realloc to the same integer pointer. If you want realloc to have the same effect as malloc, realloc does not initialize the value, that is, you need to
initialize the array to 0.

int *A = (int*)malloc(sizeof(int)*n);
free(A);

int B = (int*)realloc(NULL,n*sizeof(int));   
free(B);

image.png
This will create a new memory block without copying any data from the previous memory block
so passing in the appropriate parameters, the realloc function can be used as a replacement for the free and malloc functions

int B = (int*)realloc(NULL,n*sizeof(int)); -->malloc has the same effect

int B = (int*)realloc(A,0); -->free(A); release the memory of array A

Summarize:

  1. Several functions related to dynamic allocation of memory

malloc() calloc() realloc() free()

new delete

  1. The difference between malloc() and calloc()

When malloc() dynamically applies for memory, it will not be initialized
and calloc() will be initialized to 0

  1. Several transformation forms of realloc

(int*)realloc(B,nsizeof(int))
A =(int
)realloc(A,0) —> free(A);
(int*)realloc(NULL,n*sizeof(int));


14p pointers and dynamic memory memory leaks

The concept of dynamically allocating memory
What is a stack
What is a heap

The memory allocated for an application is usually divided into 4 segments
code area (code/test), static/global variable area (static/Global), stack (stack), heap (heap)

When dynamic memory is used incorrectly, it may lead to memory leaks.
Memory leaks refer to the fact that we dynamically apply for memory, but do not release it after use. It
will be caused by incorrect use of dynamic memory (heap)

The return value of the time() function is passed as a parameter to the srand()
srand(time(NULL)) seed value
and then the rand() function generates a series of random numbers based on the seed value

A gambling game implemented in C language

The value guessed by the play() function
is a **character array**
char C[3] = {"J", "Q", "K"};
stored in the stack,
image.png
the main function will not change during the running of the program

The result of running
game.exe consumes the memory of the system.
Keep playing, and you can see that the memory has not changed.image.png

When modifying the play() function
, modify the guessed value to a pointer type
char C = (char )malloc(3*sizeof(char));
C[0] = 'J'; C[1] = 'Q'; C[ 2] = 'K';
This belongs to opening up memory space on the heap and dynamically applying for memory
image.png

Run it again,
you will find that the memory occupied by game.exe changes with the bet we input
image.png
image.png

Let's see what happens during the running of the program

In the first case , the character array
is the memory space opened on the stack
image.png

When any function call ends, the previously allocated memory will also be reclaimed. Each function call corresponds to a stack frame. Once the call ends, the allocated memory will be reclaimed. The
release of anything on the stack does not require the programmer to take the initiative release**
this all happens automatically at the end of the function call

In the second case , use malloc to allocate memory on the heap
char C = (char )malloc(3*sizeof(char));
C[0] = 'J'; C[1] = 'Q'; C[2] = 'K';
Create an array on the heap, but only define a character pointer on the stack

A character pointer as a local variable points to a specific block of memory on the heap
Any memory on the heap is accessed through a pointer variable
image.png

When the call ends, the memory allocated on the stack will be released, but the data in the memory on the heap has been in an unreferenced state and will
not be released.
The memory on the heap must be released manually through free or through delete.
image.png

If you play multiple times, you will apply for space on the heap multiple times. The heap is not a fixed size.
If you don’t release the memory that is no longer used on the heap, you are wasting precious memory resources. The memory consumption of the application will increase over time,
so memory Leaks are dangerous
Any unreferenced and unused memory on the heap is garbage
In c/c++, as a programmer, we must ensure that no garbage is generated on the heap, memory leaks are garbage on the heap
but other languages, such as java and c#, the garbage on the heap will be automatically recovered (automatic recovery mechanism)

If the memory requested on the heap is large
and only the first few are used, if the memory is not released manually, it
will occupy a large memory space
, so call the free() function to
image.pngrun again, enter, and check the task manager, regardless of the input How many times, the game.exe file will not change.
Because free is used, the memory on the heap is manually released.
image.png
Summary

The memory on the stack is automatically reclaimed, the size of the stack is fixed, and at most only stack overflow will occur

  1. A memory leak is the inappropriate use of dynamic memory or the heap area in memory that continues to grow over a period of time
  2. Memory leaks always occur because of unused and unreferenced memory blocks in the heap
  3. Once the memory is applied in the heap, it must be released manually if it is not used or referenced

15p function return pointer

A pointer is just another data type.
A pointer stores the address of another data.
Therefore, it is allowed for a function to return a pointer.

In what scenario do we want a function to return a pointer

One implements the addition of two numbers

Value transfer Value transfer realizes the addition of two numbers
image.png
x, y, z are local variables of the main function
a, b, c are local variables of the add function

Change the local variables in main and add to the same name.
It can be seen that the value of a in the main function is copied to the function add,
but the a and b of the two are different.
image.png
Print the addresses of a corresponding to these two functions, and you will find that the two The or is not the same a, the address is different
, that is, the name of the variable is local to a function
image.png

calling function and called function
image.png

address by referenceimage.png

image.png
image.png

The function returns a pointer (address) The function returns an integer pointer
image.png
image.png

When printing helloworld before the result is displayed,
the result will be wrong
image.png

Why do you pinch like this?
When the address of c is returned, which is 144, then add ends
*ptr = 144;
image.png

At the end of the add function,
the ptr pointer points to the memory at address 144, but its value cannot be guaranteed, because this memory (the stack frame allocated by the add function) has been released.

Then call the helloworld() function.
The execution of the function call still requires stack allocation space.
The value of address 144 in the stack is overwritten by the helloworld() function, so the value in address 144 is not 6,
so some garbage values ​​are obtained.

Why is there no problem when helloworld() is not called, luck haha, maybe no other functions are called after calling add, so the machine has not rewritten the value in address 144

There is no problem in passing in the address, because the called function is always above the calling function in the stack.
Whenever the called function is executed, the calling function still exists in the memory of the stack . When add is executed, the main function can still be guaranteed to be in the In the stack, so the address of the variable in the main function is accessible to the add function

But if you try to return a local variable of the called function to the calling function, it is like returning a local variable of the add function to the main function. When the called function ends and returns to the calling function, the memory of the called function has been released.

So it is possible to pass parameters up from the bottom of the stack, and it is also possible to pass a local variable or the address of a local variable,
but it is not allowed to pass down from the top of the stack

When would we want to return a pointer from a function?
For example, if there is a memory address on the heap or a variable in the global area , then we can safely return their addresses
image.png

Therefore, the memory allocated on the heap needs to be released explicitly, and we control their release (not automatically released like the stack).
Anything in the global area, such as a global variable, has a life cycle of the entire program

So we can use malloc or C++'s new operator to open up memory on the heap

This is correct and safe, because the returned pointer on the heap
is manually created and released by the programmer.
image.png

Memory procedures
image.png
therefore return the value of the address allocated in the heap.
Any memory in the heap must be explicitly released.
Therefore, when returning pointers from functions, be aware that their scope
must ensure that the address is not reused (used to store other things), and that address is not cleared
image.png
using: linked list

Summarize

  1. Function parameters, passing by value and passing by address (passing by reference)
  2. The heap area and the stack area use malloc or new to open up memory in the heap area. If the function wants to return a pointer, it must be guaranteed that the pointer is opened in the heap area, so that there will be no error problem (abnormal value)
  3. Under what circumstances will it be required to return a pointer? When the returned variable is a global area or a global variable, a pointer can be returned.

16p function pointer

Function pointers are used to store addresses of functions.
Pointers are used to store addresses of other variables. Basically, pointers are such a data type.

The pointer points to or refers to the data in memory (the data here does not necessarily refer to variables, but can also be constants)

We not only use pointers to store addresses, but also to dereference

We can also use a pointer to store the address of a function

What is the address of the function?
image.png

A program is basically a set of sequential computer instructions, and any program that needs to be executed is encoded in a binary format

Source code --> machine code (executable code)
The compiler will take the source file as its input and generate an executable file containing machine code. The
executable file is stored on disk or other storage device

When talking about memory, it refers to the context in which the program runs, that is, random access memory (RAM), which is called main memory.
Generally, when discussing the memory of an application

When the program starts running, it will get a block of memory.
When the program ends, the memory it got will be recycled.

In fact, when we run a program, or when the program starts running, some memory will be allocated to it
image.png

The code segment is used to store the machine code or machine instructions copied from the executable file. The instructions are not directly run on the second storage medium (such as a disk), and must first be copied to the main memory before they can be executed.

Not only use memory to store instructions, but also to store a lot of data during operation.
Other sections are mainly used to store and manage data

The order of instructions in a program is executed sequentially.
The only exception is function calls.
image.png

A function is a group of instructions stored in a contiguous block of memory
Basically a function is a group of instructions used to perform a subtask
In memory, a function is a contiguous block of memory (in which are instructions)
the address of the function, also called It is the entry point of the function , which is the address of the first instruction of the function
image.png

A function call in machine language is basically a jump instruction
Jump to the entry point of the function, jump to the first instruction of the function

The function pointer stores the address of the function, and the function pointer stores the starting address or entry point of the function in memory.

How to create a function pointer in c/c++

int (*p)(int,int)

The parameter type declared in the function pointer must be the same as the parameter of the pointed function
image.png
Initialize the function pointer and fill in the address of the function

p = &Add; //Return the address of Add to p, fill in the address of the initialization function pointer

Pass by value
image.png
uses a function pointer to refer to a function
Use * dereferencing to get the function

c = (*p)(2,3);   // *p 就相当于 Add函数

image.png

if so write

int *p(int,int);   //声明了一个函数  这个函数返回一个整型的指针

The difference between returning a pointer and returning a function
Returning a pointer
image.png
Returning a function pointer
image.png

The function pointer can be initialized without using the address symbol, and the address of the function can be returned only by using the function name
image.png

"" can be understood as a pointer, which is a pointer constant, pointing to a string in the constant area, and the value is equal to the address of the string
image.png

Summarize

  1. function pointer
  2. Two ways to reference and dereference
  3. In order to point to a function, the function pointer must be of the correct type
  4. The function pointer stores the address of the function, and stores the starting address (entry point) of the function in memory

17p Use Case of Function Pointer Callback Function

Function pointers can be used as parameters of functions.
The function that receives the function pointer can call back the function pointed to by the function pointer.
image.png

It can also be written like this
because function A, the function name A itself returns a pointer.
When a function reference is passed to another function, that function is called
a callback function. callback A
image.png

Example 1
Sort the array in ascending order and
image.png
sort in descending order
image.png

Use the pointer callback function,
image.png
this is something,
image.png
change the compare function
image.png

Array elements are sorted in ascending order of absolute value
image.png

Sort array elements in ascending order Sort
image.png
image.png
array elements in descending order
image.png
image.png

The absolute value of the array is arranged in ascending order
image.png
. In the compare comparison function, the functions with comparison are passed by reference, and their addresses are passed by pointer.

The qsort function can sort any array, not just an integer array, we need to give our own comparison logic
Callback idea
Event handling


18p pointer and application – based on ARM Cortex-M

Computer memory is viewed as an array of bytes, each byte has a unique address
Computer memory is byte addressable
The smallest addressable data object is a byte

ARM Cortex-M microprocessor, each memory address has 32 bits, can address a total of 4GB
image.png

A data object may occupy multiple bytes in memory
For example a word occupies 4 bytes in memory
There are two different formats to store a word
min-endian, max-endian

When storing a word in least-endian format, the most significant byte is stored at the high address and the least significant byte at the low address
When storing a word in max-endian format, the most significant byte is stored at the low address and the least significant byte is stored at the high address address
image.png

The value of the pointer is simply the memory address of some variable stored in the computer

If a variable occupies more than one byte in memory, the variable's address is defined as the lowest address of all the bytes it occupies
image.png

Reference operator and dereference operator The reference operator
&x, returns the address of the x variable, & is called the reference operator or address operator The
dereference operator *p returns the value of the variable pointed to by the pointer p
image.png

image.png

Summary
The reference operator works on variables, and can read the address of the variable. &var is the address of var. The
dereference operator can handle pointers, and can read the value of the variable pointed to by the pointer.
image.png

The pointer to the character array does the mathematical operation
ptr++, adding sizeof (type)
image.png

Integer pointers do mathematical operations
ptr = ptr + sizeof(int);
image.png

Example
Arrays and Pointers
ArrayName is a pointer to the first of the array elements
image.png

Operators
Increment and decrement operators, higher rank than dereference operator*
image.png

How to create a pointer to a given specific memory address

For example, the memory address of the output data register of the GPIOA is determined by the designer of the microcontroller at design time in order
to establish a pointer to it, so that software can easily access the output data register
image.png
to convert the constant address into a pointer, pointing to an unsigned 32-bit integer, then use the dereference operator to access the pointed-to value

For example, set GPIOA5 to high level
and use a macro to define a pointer. This macro will force the memory address into a pointer, so you can directly dereference the value of this address. Put the
image.png
dereference operator directly into the macro, so that the software can directly use the dereference Referenced pointers
are most commonly used to access memory
image.png

If you force the compiler to read a new value every time, adding the keyword volatile
can prevent the compiler from making wrong optimizations during compilation
image.png

In the device header file of the STM32 Cortex-M processor , **The memory address of the peripheral is forced to point to a structure **
Use a macro to cast this memory address into a pointer, which can be a GPIO type structure , so that the data output registers can be modified in this way
Using the structure, the software can access all registers of the peripheral more easily
image.png

material
image.png

It's over, sprinkle flowers, Ollie! ! ! It took 5 days, and the learning of linux was mixed in it!!!


3. Pointer heima programmer notes

This is the pointer teaching video learned by the black horse programmer. It is relatively simple, so let’s summarize it together.

Pointers can access memory indirectly

1. Definition and use of pointers

  • The memory numbers are all recorded from 0, generally expressed in hexadecimal
  • Pointer variables can be used to hold addresses
  1. Define pointer data type* pointer variable name
  2. You can add * before using the pointer pointer to dereference and find the data pointed to by the pointer in memory
#include <iostream>

using namespace std;

int main()
{
    
    
    // 1. 定义指针
    int a = 10;
    int *p = &a;
    cout << "a的地址为:" << &a << endl;
    cout << "指针p为:  " << p << endl;

    // 2. 使用指针
    // 可以通过解引用的方式来找到指针指向的内存  可以修改也可以访问
    // 指针前 可以加 * 表示解引用 找到指针指向内存中的数据
    *p = 1000; //指针p通过解引用找到了a的地址 修改a的值为1000
    cout << "a的值为:" << a << endl;
    cout << "*p的值为:" << *p << endl;
    system("pause");
    return 0;
}

2. The memory space occupied by the pointer

Note that under the same operating system, the bytes occupied by pointers of any data type are the same

比如,在64位操作系统中,int * 占8字节,float * 占8字节,double * 占8字节

int *p
occupies 4-bit memory space under 32-bit system
and occupies 8-bit memory space under 64-bit system

#include <iostream>

using namespace std;

int main()
{
    
    
    // 指针所占内存空间
    int a = 10;
    int *p = &a;
    // 64位 占8字节
    cout << "sizeof(int *) = " << sizeof(int *) << endl;
    cout << "sizeof(p) = " << sizeof(p) << endl;

    // 在相同的操作系统下,不同数据类型的指针所占字节都是相同的
    cout << "sizeof(char) = " << sizeof(char *) << endl;
    cout << "sizeof(flaot) = " << sizeof(float *) << endl;
    cout << "sizeof(double) = " << sizeof(double *) << endl;
    cout << "sizeof(long) = " << sizeof(long *) << endl;
    system("pause");
    return 0;
}

3. Null pointers and wild pointers

  • Null pointer: The pointer variable points to the 0 space in the memory
    for initializing the pointer variable.

The memory pointed to by the null pointer is inaccessible

#include <iostream>

using namespace std;

int main()
{
    
    
    // 1. 空指针用于给指针变量初始化
    int *p = NULL;

    // 2. 空指针不可以进行访问
    // 0-255 之间的内存由系统占用 因此不可以访问
    *p = 100;
    cout<<*p<<endl;  //没有权限
    system("pause");
    return 0;
}
  • Wild pointer
    Pointer variable points to illegal memory space
#include <iostream>

using namespace std;

int main()
{
    
    
    //在程序中,尽量避免野指针出现 即指针指向非法的内存空间
    int *p = (int *)0x1100;
    cout << *p << endl;  //访问野指针报错
    system("pause");
    return 0;
}

4. const modified pointer

const followed by a variable is called a constant.

Three cases of const modified pointer

  1. const Modified pointer constant pointer
    The pointer can be modified, but the pointed value cannot be modified

const int *p = &a;

#include <iostream>

using namespace std;

int main()
{
    
    
    int a = 10;
    int b = 20;
    const int *p = &a;
    cout << "为修改指向前*p的值为:" << *p << endl;
    p = &b; //常量指针可以修改指向
    cout << "修改指向后*p的值为:" << *p << endl;
    // *p = 30;  报错 常量指针 不可修改值

    system("pause");
    return 0;
}
  1. const Modified constant pointer constant
    The point pointed by the pointer cannot be modified, but the value pointed to can be modified

int * const p=&a;

#include <iostream>

using namespace std;

int main()
{
    
    
    int a = 10;
    int b = 20;
    int *const p = &a;

    //指针常量可以修改值,不可以修改指针的指向
    *p = 100;
    cout << "*p = " << *p << endl;
    // p = &b;  报错 不可以修改指针的指向
    system("pause");
    return 0;
}
  1. const modifies pointers, and modifies constants.
    Neither the pointer nor the pointed value can be modified.

const int _ const _p=&a;

#include <iostream>

using namespace std;

int main()
{
    
    
    int a = 10;
    int b = 20;
    const int *const p = &a;

    // *p = 100; 报错 不可以修改指针的值
    cout << "*p = " << *p << endl;
    // p = &b; 报错 不可以修改指针的指向
    system("pause");
    return 0;
}

5. Pointers and arrays

Access array elements using pointers

#include <iostream>

using namespace std;

int main()
{
    
    
    // 利用指针访问数组中的元素
    int arr[10] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    cout << "数组的第一个元素的值为:" << arr[0] << endl;

    int *p = arr; //指针p指向数组的首地址
    cout << "访问指针访问的第一个元素:" << *p << endl;

    p++; //指针偏移了int类型变量的地址 即偏移地址4位
    cout << "利用指针访问的第二个元素:" << *p << endl;

    cout << "访问第三个元素的值:" << *(p + 1) << endl;

    // 利用指针遍历数组
    int *p1 = arr;
    for (int i = 0; i < 10; i++)
    {
    
    
        cout << *(p1 + i) << endl;
    }

    system("pause");
    return 0;
}

6. Pointers and functions

By using pointers as parameters of functions, the values ​​of actual parameters can be modified.

The formal parameter of the function is a pointer, which can reduce the memory space.

#include <iostream>

using namespace std;

void swap1(int a, int b)
{
    
    
    int temp = a;
    a = b;
    b = temp;
    cout << "a的值为:" << a << endl;
    cout << "b的值为:" << b << endl;
}

void swap2(int *p1, int *p2)
{
    
    
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
int main()
{
    
    
    // 指针和函数
    // 1. 值传递
    // 值传递不会修改实参
    int a = 10, b = 20;
    swap1(a, b);
    cout << "swap1 a的值为:" << a << endl;
    cout << "swap1 b的值为:" << b << endl;

    // 2. 地址传递
    // 地址传递 可以修改实参的值 
    swap2(&a, &b);
    cout << "swap2 a的值为:" << a << endl;
    cout << "swap2 b的值为:" << b << endl;
    system("pause");
    return 0;
}

7. The case of pointer array function

Encapsulate a function and use bubble sorting to sort integer arrays in ascending order

For example arrays,

#include <iostream>

using namespace std;

void arraySort(int *arr, int length)
{
    
    
    //冒泡排序
    for (int i = 0; i < length - 1; i++)
    {
    
    
        for (int j = 0; j < length - 1 - i; j++)
        {
    
    
            if (arr[j] > arr[j + 1])
            {
    
    
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
int main()
{
    
    
    int arr[10] = {
    
    4, 3, 6, 9, 1, 2, 10, 8, 7, 5};
    int length = sizeof(arr) / sizeof(arr[0]);
    // 排序前
    cout << "未排序前:" << endl;
    for (int i = 0; i < length; i++)
    {
    
    
        cout << arr[i] << " ";
    }
    cout << endl;
    //排序
    arraySort(arr, length);
    //排序后
    cout << "排序后:" << endl;
    for (int i = 0; i < length; i++)
    {
    
    
        cout << arr[i] << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

Guess you like

Origin blog.csdn.net/cyaya6/article/details/132245789