[C language: In-depth understanding of pointers 1]


Insert image description here

1.The meaning of pointer existence

Speaking of C language, are you most afraid of pointers? After reading the following content, you may not be so timid about pointers.
First of all, we need to understand why there are pointers in C language.

  • Pointers are the soul of the C language. This statement is not an exaggeration. Pointers are one of the most basic and important concepts in the C language. They make the C language a powerful, efficient, and flexible programming language.
  • existence of pointersAllows C language to perform complex memory operations, can better control the behavior of the program, and can also implement efficient data structures and algorithms.
  • 指针是一个变量,它存储了一个内存地址,而这个内存地址指向的是另一个变量或对象的位置. Through pointers, we can directly access or modify the variables or objects at this location, which provides us with great flexibility and control.

In computers, we also call the number of a memory unit an address. In C language, a new name is given to addresses: pointers.
So we can understand it as: Memory unit number = address = pointer

2. Pointer variables and addresses

  1. In C language, creating a variable is to apply for space in memory, as shown below:

Insert image description here
The above code creates an integer variable a and applies for 4 bytes of space in the memory. Each byte has its own address.
&a takes out the share of aThe address of the smaller byte of the 4 bytes., we know its address, and we can follow the clues to access 4 bytes of data.

  1. How to get the address of a variable?

The address we get through the address operator (&) is a numerical value, such as: 0133FE28. Sometimes this value also needs to be stored for easy use later, then we put it like this Where is the address value stored? The answer is: in the pointer variable.
The way to write a pointer variable is to add a *
Insert image description here
before the variable. The pointer variable is also a kind of variable, and this kind of variable is used to store addresses, the value stored in the pointer variable will be understood as an address. 指针变量也有自己的地址, the address of pa here is 0x00cffdfc.

  1. How to get variable by address?

As long as we get the address (pointer), we can use the address (pointer) to find the object pointed to by the address (pointer). Here we must learn an operator called the dereference operator (*).
Insert image description here

  1. size of pointer variable
  • size of pointer variableDepends on the size of the address, regardless of the type of the pointer variable.
  • On a 32-bit platform, the address is 32 bits, which is 4 bytes.
  • On a 64-bit platform, the address is 64 bits, which is 8 bytes.

Insert image description here

3. The meaning of pointer variable type

3.1 Pointer dereference

Insert image description here
Insert image description here
We can see through debugging that the first one will change all 4 bytes of a to 0, and the second one will only change the first byte of a to 0.
Conclusion:The type of the pointer determines how much authority you have when dereferencing the pointer (you can operate several bytes at a time)

3.2 Pointer + - Integer

Insert image description here

From the above figure, we can find that the int type pointer + 1 skips 4 bytes, and the char type pointer + 1 skips 1 byte.
Conclusion:The type of pointer determines how far (distance) the pointer moves forward or backward.

3.3void*

There is a special type among pointer types, which is the void* type, which can be understood as a pointer without a specific type (or a generic pointer), 这种类型的指针可以⽤来接受任意类型地址. But there are limitations, Pointers of void* type cannot directly perform pointer + - integer and dereference operations.

  • void* pi can accept any type of address

Insert image description here

  • Pointers of void type cannot be dereferenced or added or subtracted from integers.

Insert image description here

4.Keyword const

4.1const modified variables

If we want to add some restrictions to a variable and cannot be modified, what should we do? This is what const does.

  • When const modifies a variable, the value of the variable cannot be modified.

Insert image description here

4.2 const modified pointer

  • const is to the left of the * sign

Insert image description here

  • const is to the right of the * sign

Insert image description here

  • const on both sides of *

Insert image description here

Summarize::Left fixed value, right oriented

5. Pointer arithmetic

5.1 Pointer + - Integer

Insert image description here

Insert image description here

5.2 Pointers - pointers

  • Pointer-pointer绝对值 is the number of elements between the two pointers (Both pointers must point to the same space

Insert image description here

5.3 Pointer size comparison

  • Pointer comparison is the address comparison.

Insert image description here

6. Wild pointer

Concept: Wild pointers areThe location pointed by the pointer is unknowable(Random, incorrect, no clear limit)
How are wild pointers caused?

  1. Pointer not initialized

Local variables are not initialized and default to random values.
Insert image description here

  1. Pointer out-of-bounds access

Insert image description here

  1. The space pointed to by the pointer is released

Insert image description here

The reason why 10 can be printed is because the stack frame space of the test function has not been destroyed. When it is printed again, it becomes a random value.

Although pointers are good, irregular use of pointers may cause unexpected consequences, so wild pointers should be avoided when using them.

How to avoid wild pointers?

  1. Pointer initialization
  2. Don’t cross-border access
  3. Pointer variables are promptly set to NULL when not in use.
  4. Check if pointer is NULL before use

7.assert affirmation

The assert.h header file defines the macro assert(), which is used to ensure that the program meets the specified conditions during runtime. If it does not meet the requirements, an error will be reported and the execution will be terminated. This macro is often called an "assertion".
The assert() macro accepts an expression as a parameter. If theThe expression is true (the return value is non-zero), assert() has no effect, the program continues to run. If the表达式为假(返回值为零), assert() 就会报错,在标准错误流 stderr 中写⼊⼀条错误信息,显示没有通过的表达式,以及包含这个表达式的⽂件名和⾏号,如下:

#include<stdio.h>
#include<assert.h>
int main()
{
    
    
	int* p = NULL;
	assert(p != NULL);
	printf("66666\n");
	return 0;
}

Insert image description here
Using assert() has several benefits: not only does it automatically identify the file and line number of the problem, it also has a mechanism to turn assert() on or off without changing the code. If it is confirmed that there is no problem with the program and there is no need to make assertions, just define a macro NDEBUG before the #include <assert.h> statement.
Insert image description here
Generally, we can use it in Debug, and just choose to disable assert in the Release version. In an integrated development environment like VS, in the Release version, it is directly optimized. In this way, writing in the debug version is helpful for programmers to troubleshoot problems, and writing in the Release version does not affect the efficiency of the program when users use it.

8. Understanding array names

  • The array name is the address of the first element of the array, but there are 2 exceptions!

Insert image description here

  • Exception 1

sizeof(array name),sizeof中单独放数组名,数组名表示整个数组的大小, the unit is bytes.
Insert image description here

  • Exception 2

&数组名,取出的是整个数组的地址(There is a difference between the address of the entire array and the address of the first element of the array)

Insert image description here
Here we find that &arr[0] and &arr[0]+1 differ by 4 bytes, and arr and arr+1 differ by 4 bytes, because both &arr[0] and arr are first elements. Address, +1 isSkip an element.
But the difference between &arr and &arr+1 is 40 bytes. This is because &arr is the address of the array and the +1 operation is Skip the entire array.
At this point, everyone should understand the meaning of the array name.

9. The essence of passing parameters through one-dimensional arrays

First, let’s start with a question. We used to calculate the number of elements of the array outside the function. Can we pass the function to a function and then find the number of elements of the array inside the function?
Insert image description here
We found that the result was not what we wanted. Inside the func function, the size of sizeof(arr) is not 40, but 4. Why is this?

  • After studying the array name, we know that the array name is the address of the first element of the array;
  • Then when passing parameters in the array,What is passed is the array name, which means that in essence, the array parameter is passed the address of the first element of the array.
  • sizeof an address, then its size must be 4/8 bytes, so the result will be 1.
  • So we can understand:一维数组传参,传递的是数组首元素的地址。When the parameter we receive is an array name, it can be written in the form of a pointer.
void test(int* arr)//参数写成指针形式
{
    
    
 	printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
}
  • When the compiler processes the access to the array element, it is also converted into ⾸元素的地址+偏移量 to find the address of the element, and then dereferences it for access.

Guess you like

Origin blog.csdn.net/weixin_69380220/article/details/134351238