Detailed explanation of C language pointer content

Hello everyone, today we are going to learn about pointers.

pointer

What is a pointer?

  1. A pointer is the number of a smallest unit in memory, that is, the address
  2. The pointer we usually talk about in spoken language usually refers to a pointer variable, which is a variable used to store a memory address.

Pointers can also be said to be addresses, but pointers in our spoken language are usually pointer variables.

Insert image description here

Let us see this memory map, we should know that the pointer variable is where we store the address in a variable through the & symbol. This variable is called a pointer variable.

#include <stdio.h>
int main()
{
    
    
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
中,p就是一个之指针变量。
return 0;
}

We have created a pointer variable. So what should we do if we want to print a?
Insert image description here
Here, the pointer variable p stores the address of a. If we dereference p, the object pointed to by *p is a=10, so if we print *p, we can print out the result.
Summary:
Pointer variables are variables used to store addresses. (The values ​​stored in pointers are treated as addresses).

So how big is a small unit? It is a byte. We give each byte an address to organize. For a machine with 32 address lines, all pointer type values ​​are a 32-bit integer, then there will be 2 32nd power address, which is 232th power bytes, then we can calculate it to be 4GB of memory. This is how much memory a 32-bit machine can program.

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

Pointers and pointer types

The definition of pointer is: type + *
char* type pointer is to store the address of char type variable.
The short* type pointer is used to store the address of the short type variable.
The pointer of type int* is used to store the address of the variable of type int.

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

Insert image description here
We see that the address difference between pa and pa+1 is four bytes, and the address difference between pc and pc+1 is one byte, so the pointer of int is increased by 1 and skips four bytes, while the pointer of char Add 1 to skip one byte, add 1 to the short pointer to skip two bytes, and add 1 to the double pointer to skip eight bytes.

Summary:
The type of the pointer determines how much authority it has when dereferencing the pointer (how many bytes it can operate).
For example: dereferencing a pointer to char* can only access one byte, while dereferencing a pointer to int* can access four bytes.

The next thing we need to pay attention to is how to avoid wild pointers.

wild pointer

Concept: A wild pointer means that the position pointed by the pointer is unknown (random, incorrect, and without clear restrictions)

If the pointer is not initialized, a wild pointer will appear.

#include <stdio.h>
int main()
{
    
    
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
printf("%d\n", *p);
return 0;
}

When we run it, we will find that the system reports an error.
Insert image description here

In addition, out-of-bounds pointer access can also lead to the emergence of wild pointers.

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
    0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
    
    
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
printf("%d", *p);
return 0;
}

Insert image description here
This is because the access is out of bounds, which leads to wild pointers.

So how can we effectively avoid wild pointers?

1. Pointer initialization
2. Be careful of
pointer out of bounds 3. Set NULL even if the space pointed to by the pointer is released
4. Avoid returning the address of local variables
5. Check the validity of the pointer before using it

NULL is called a null pointer. If it is not clear which variable the pointer points to, you need to assign a NULL value. This is used when we do not know which variable the pointer points to.

int *p=NULL;
int *p=0;

We use these two methods to obtain the null pointer.

#include <stdio.h>
int main()
{
    
    
int *p = NULL;
//....
int a = 10;
p = &a;
if(p != NULL)
{
    
    
*p = 20;
}
printf("%d", a);
return 0;
}

Insert image description here
Here we find that we can run it after obtaining the null pointer.

pointer arithmetic

Pointer ± integer
pointer-pointer
relational operation of pointer

pointer ± integer

int main()
{
    
    
	int arr[] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//            0 1 2 3 4 5 6 7 8 9
	//使用指针打印数组的内容
	int * p = arr;
	int i = 0;

	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", *(p + i));
		//printf("%d ", *(arr + i));
		//printf("%d ", arr[i]);
		//printf("%d ", i[arr]);
	}
	return 0;
}

Insert image description here
Here we add an integer to the pointer and dereference *(p+i) to print the array. p points to the first element of the array. p+i is the address of the element subscripted i in the array. i is skipped at the beginning. *sizeof(int) bytes.

pointer - pointer

int main()
{
    
    
	int arr[10] = {
    
     0 };
	printf("%d\n", &arr[9] - &arr[0]);
	printf("%d\n", &arr[0] - &arr[9]);

	return 0;
}

Insert image description here
Note:
The premise of pointer-pointer: two pointers point to the same area, and the pointer type is the same. The absolute
value of the pointer-pointer difference, the number of elements between the pointer and the pointer.

Relational arithmetic on pointers
allows a pointer to an array element to be compared with a pointer to a memory location after the last element of the array, but not to a pointer to a memory location before the first element.

pointers and arrays

Next we see the code:

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

Insert image description here
It can be seen that the array name and the address of the first element of the array are the same. So we understand that the array name represents the address of the first element of the array.

int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址

In this way, we store the address of the first element of the array into the pointer p.

#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]);
for(i=0; i<sz; i++)
{
    
    
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
}
return 0;
}

Insert image description here
In this way, we can also find that p+i actually calculates the address subscripted as i in the array arr.

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));
	}
	return 0;
}

Insert image description here
Here we first store the first element of the array into a pointer, and then use the pointer plus integer operation to dereference (p+i) to completely print out the entire array.

secondary pointer

Pointer variables are also variables. Variables have addresses. So where is the address of the pointer variable stored?
This is the secondary pointer. In layman's terms, secondary pointers are used to store pointer variables.

Insert image description here

** ppa dereferences the address in ppa, so that it finds pa. In fact, ppa actually accesses pa.

int b = 20;
*ppa = &b;//等价于 pa = &b;

**ppa first finds pa through *ppa, and then dereferences pa: *pa, then it finds a.

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

Here **ppa is relative to dereferencing pa to get *pa=30.

Okay, that’s it for today’s sharing, thank you all.

Insert image description here

Guess you like

Origin blog.csdn.net/Lehjy/article/details/132356628