C language - complete version of pointers

Table of contents

1. Pointer operations

1.1 pointer +- integer

1.2 Pointers – Pointers

1.3void* pointer

2. Pointer traversal of array

2.1 Pointer traversal of array

1. Understand the meaning of array names (& the difference between array names and array names).

2. Traverse the array using pointers 

3. Pointer array, array pointer, function pointer

3.1 Pointer array

3.1.1 Form of pointer array

3.1.2 Use cases of pointer arrays

3.2 Array pointer

3.3 Function pointers

3. Array of function pointers

3.1 Form of function pointer array

3.2 Purpose of function pointer array: transfer table

4. Array as function body parameter

5. Use arrays as return values ​​in functions

5.1 Return the address of a static local array

5.2 Return the address of the string in the literal constant area

5.3 Return the address of the heap content

5.4 Summary


1. Pointer operations

1.1 pointer +- integer

Summary: The type of pointer determines how far (distance) the pointer moves forward or backward.

1.2 Pointers – Pointers

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

When we want to use two pointers to subtract, we can guess from the above picture, is the output the number of elements between the two addresses or the difference (byte) between the two addresses?

By running we can know that the result of pointer - pointer: the number of elements between the pointer and the pointer.

So can any two pointers be subtracted? From the above answers we can get:

Pointer - The premise of pointer : two pointers point to the same area and the pointer type is the same.

So if we use a small pointer - a large pointer, our result becomes -9.

So we can get a more rigorous conclusion:

Pointer - the result of a pointer : its absolute value is the number of elements between pointers.

1.3void* pointer

Pointers of type void* cannot be used for dereference operators, nor can they be used for + - integer operations.

A pointer of type void* is used to store the address of any type of data.

void* Pointer without concrete type

You can use void* pointers to receive pointers of any type. If you need to dereference a void* pointer, you can cast it.

2. Pointer traversal of array

2.1 Pointer traversal of array

1. Understand the meaning of array names (& the difference between array names and array names).

The array name is the address of the first element of the array. There are two exceptions:
1. sizeof(array name), calculates the size of the entire array, sizeof puts a separate array name inside, and the array name represents the entire array.
2. & array name takes out the address of the array. & array name, the array name represents the entire array.
Except for the two cases 1 and 2, all array names represent the address of the first element of the array.

Let's look at a piece of code to understand the difference between & array name and array name.

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;
}

According to the above code, we found that in fact, although the values ​​of &arr and arr are the same, their meanings should be different.
In fact: &arr represents the address of the array , not the address of the first element of the array.
The address of the array is +1 , skipping the size of the entire array, so the difference between &arr+1 and &arr is 40.

2. Traverse the array using pointers 

Since the array name can be stored in a pointer as an address, it becomes possible for us to use a pointer to access one.

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

 As you can see, we can traverse each element of the array through a pointer:

p+i actually calculates the address of the array arr with index i .
Then *(p+1) can access each element of the array arr .

3. Pointer array, array pointer, function pointer

3.1 Pointer array

A pointer array is an array that stores pointers.

3.1.1 Form of pointer array

Let’s first take a look at what a pointer array looks like (the same applies to other types):

int* arr[5];    //数组名称:arr  数组元素个数:5  数组元素的类型:int* 

So what is the use of knowing an array of pointers?

3.1.2 Use cases of pointer arrays

We already know that the array name represents the address of the first element of the array in most cases, so we can use a pointer array to simulate a two-dimensional array.

int arr1[] = { 0,1,2,3,4,5 };
int arr2[] = { 1,2,3,4,5,6 };
int arr3[] = { 2,3,4,5,6,7 };

int* arr[] = { arr1,arr2,arr3 };

So how should we use this simulated two-dimensional array?

We can access it directly using its subscript.

the difference:

The difference between our simulated array and a real two-dimensional array is that the element address of each element of the real two-dimensional array is continuous, while the one-dimensional array address of each one-dimensional array of the simulated two-dimensional array is not continuous.

3.2 Array pointer

An array pointer is a pointer to an array.

int(*p)[10];
	/*
	解释:p先和 * 结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。
	所以p是一个指针,指向一个数组,叫数组指针。
	*/
	//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

We know that integer, full-precision floating point, etc. all have a data type, int, double... Of course, here, the array pointer also has its data type.

3.3 Function pointers

Let’s take a look at a piece of code first

#include <stdio.h>
void test()
{
 printf("hello!\n");
}
int main()
{
 printf("%p\n", test);//打印test地址
 printf("%p\n", &test);//打印&test地址
 return 0;
}

From the running results, we can see that the function name and the array name actually have the same effect. However, for the convenience of observation, when we need the function address in the future, we will still use & function name to implement it .

If we want to use a pointer to store the above test function, what should we do?

void(*pf)() = &test;
pf1 is first combined with *, indicating that pf1 is a pointer. The pointer points to a function. The pointed function has no parameters and the return value type is void.

From the above we can get:

int max(int a, int b)
{
	if (a > b)
		return a;
	else
		return b;
}
int main()
{
	int (*pf2)(int, int) = &max;
	return 0;
}

In this way we can clearly understand the form of function pointers.

3. Array of function pointers

3.1 Form of function pointer array

An array is a storage space that stores data of the same type. We have already learned about pointer arrays.
for example:
int * arr [ 10 ];
// Each element of the array is int*
Then we need to store the address of the function in an array. Then this array is called an array of function pointers. How to define the array of function pointers?
(Take the above int max(int ​​a, int b) as an example, assuming that the function pointer array stores such functions)
int( * parr[ 10])( int, int);
Parr is first combined with [ ], and parr appears to be an array.
What is the content of the array?
It is a function pointer of type int (*)(int, int) .

3.2 Purpose of function pointer array: transfer table

Let's take a simple calculator as an example to see the convenience of using an array of function pointers.
What to prepare:
When the function pointer array is not used, we need to call one function one by one according to the user input:
After using the function array, we only need to encapsulate all four functions in the preparation phase into an array of function pointers:

When we use it next time, we can use it flexibly:

Isn’t it simplified a lot?

4. Array as function body parameter

When defining the function body, when the parameter is an array, it can be received using either an array or a pointer. The use of array receiving has nothing to do with the element subscript of the array.

5. Use arrays as return values ​​in functions

Returning an array is actually returning a pointer.

char* fun()
{
	char str[100] = "hello world!";
	return str;
}
int main()
{
	char* pf;
	pf = fun();

	printf("%s\n", pf);

	return 0;
}

5.1 Return the address of a static local array

The above code has an obvious flaw:

str is created in the fun function body and is a temporary variable. When we want to use pf to receive it in the main function, str has been destroyed. At this time, we can modify our str with static in the fun function to extend it. its life cycle.

The operation is as shown in the figure:

5.2 Return the address of the string in the literal constant area

A constant string is a constant and always exists.

5.3 Return the address of the heap content

malloc header file:

#include<stdlib.h>

malloc dynamically applies for memory for str, the size is 100, and the unit is bytes. The dynamically allocated memory will not be released after the function ends.

The contents of the heap area always exist until free.

5.4 Summary

The returned address and the content of the memory pointed to by the address must exist to be meaningful.

Guess you like

Origin blog.csdn.net/m0_75186846/article/details/132081257