[pointer doll] advanced explanation of pointer

preface

First, let's review the concept of pointers

  1. A pointer is a variable used to store an address, which uniquely identifies a piece of memory space.
  2. The size of the pointer is fixed at 4 / 8 bytes (32-bit platform / 64 bit platform).
  3. Pointers are typed. The pointer type determines the step size of the + (-) integer of the pointer and the permission of pointer dereference operation.
  4. Pointer operation.

1, Character pointer

There are generally two types of character pointers:

int main()
{
    //First, point to a single character
    char ch='w';
    char* p=&ch;
    
    //Second, point to a constant string
    char* ptr="hello world!";//But does ptr store the whole string?
    return 0;
}

It's especially easy to think that the constant string hello world! Put it into the character pointer ptr, but the essence is to put the address of the first character of the string into ptr, that is, ptr points to the address of 'h', but the string is continuously stored in memory, and the system automatically adds the end of '\ 0' to the end of the string. When% s is used to output the character string, it will continue to output from the first element to the end of '\ 0'.

Then there are such interview questions:

#include <stdio.h>
int main()
{
  char str1[] = "hello world!";
  char str2[] = "hello world!";
  char *str3 = "hello world!";
  char *str4 = "hello world!";
  if(str1 ==str2)
	printf("str1 and str2 are same\n");
  else
	printf("str1 and str2 are not same\n");

  if(str3 ==str4)
	printf("str3 and str4 are same\n");
  else
	printf("str3 and str4 are not same\n");
  return 0;
}

Please read your answer in your heart.

As we know from the above, character pointers and array pointers store the first address of the element, so the first address is compared.

Here, str3 and str4 point to the same constant string. C/C + + will store the constant string in a separate memory area when several pointers. When pointing to the same string, they actually point to the same block of memory. However, when initializing different arrays with the same constant string, different memory blocks will be opened up. So str1 and str2 are different, and str3 and str4 are the same.

2, Pointer array

We also learned pointer arrays earlier

Let's review here. What does the following pointer array mean?

int* arr1[10]; //Array of shaping pointers (storing shaping pointers)
char *arr2[4]; //Array of first level character pointers (storing character pointers)
char **arr3[5];//Array of L2 character pointers (storing L2 character pointers)

How to determine the type of array storage?

Very simple. Remove the "array name []" directly, and the rest is the type of array.

3, Array pointer

Definition of array pointer

Is an array pointer a pointer or an array?
The answer is: pointer.

We can deduce from previous studies that the character pointer char* p and the integer pointer int* p.
So the array pointer should be: a pointer that can point to an array.
How to express it
First, it is a pointer. When defining, you need to add * before the variable. Secondly, the type it points to is an array, so there are the following definitions

int arr[10]={0};
//Define an array pointer parr to point to arr
int (*parr)[10]=&arr;
//*parr must be enclosed in parentheses because [] takes precedence over*

It can also be explained from an expression
parr is first combined with * to indicate that parr is a pointer variable, and then points to an array of 10 integers. Therefore, p is a pointer to an array, which is called array pointer.

int main()
{
	int a = 10;
	int* pi = &a;//The address of an integer is stored in an integer pointer
	char ch = 'w';
	char* pc = &ch;//The address of the character is stored in the character pointer

	int arr[10] = {0};
	int* p = arr;// -Is the address of the first element of the array

	//int* parr[10]; / / this is an array
	int (*parr)[10] = &arr;//What is taken out is the address of the array, which should be stored in the array pointer

	return 0;
}

&Array name VS array name

For the following array:

int arr[10];

What are arr and & arr?
We know that arr is the array name, which indicates the address of the first element of the array.
What is the &arr array name?
Let's look at a code:

#include <stdio.h>
int main()
{
  int arr[10] = {0};
  printf("%p\n",&arr[0]);
  printf("%p\n", arr);
  printf("%p\n", &arr);
  return 0;
}

Their values are the same
Therefore, we can conclude that & arr and arr at this time point to the first element of the array, which is the address of the first element. It should be noted that their types are different, namely int ()[10] and int *.

But does arr always point to the first element of the array?

It is concluded that arr has different meanings in different places.
When the array name (arr) is the first element address except for the following two cases

1. Sizeof (array name), where the array name represents the entire array. Sizeof (array name) calculates the size of the entire array in bytes
2. & array name. The array name here is not the address of the first element. The array name represents the whole array, so the address of the whole array is taken out

The code is as follows:

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };

	//Calculate the size of the entire array
	printf("%d\n", sizeof(arr));
	
	//The extracted address is the address of the whole array
	int(*parr)[10] = &arr;
	return 0;
}


Let's look at the difference

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	//arr is the first element address
	//&Arr [0] is the first element address
	//&Arr fetches the address of the array

	printf("%p\n",arr );
	printf("%p\n",&arr[0] );
	printf("%p\n", &arr);

	printf("%p\n", arr+1);
	printf("%p\n", &arr[0]+1);
	printf("%p\n", &arr+1);

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(&arr));


	int(*parr)[10] = &arr;
	return 0;
}


Summary:

  • Arr (not two exceptions) and & arr [0] are the first element addresses
  • &Arr is the address of the array, not the address of the first element of the array, so & arr + 1 skips the entire array (40 bytes)
  • The first element address + 1 is the address of the second element
  • sizeof(arr) is the size of the entire array
  • Yes, the address size is 4 / 8

Use of array pointers

How are array pointers used?
Since the array pointer points to an array, the address of the array should be stored in the array pointer.
Look at the code:

#include <stdio.h>
int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,0};
  int (*p)[10] = &arr;//Assign the address of array arr to array pointer variable p
  //But we rarely write code like this
  return 0;
}

4, Function pointer

That is, the pointer to the function to store the address of the function.
Let's look at a piece of code

#include <stdio.h>
void test()
{
	printf("hehe\n");
}
int main()
{
	printf("%p\n", test);
	printf("%p\n", &test);
	return 0;
}


Both values are the address of the function. How to save the address of the function?

You need to define a function pointer to receive the address of the function.
First, the function pointer is a pointer, which needs to be combined with * first, and then with (), indicating that it points to a function, and () contains the formal parameter type of the function, as well as the return value of the function.

void test()
{
	printf("hehe\n");
}
//Which of the following pfun1 and pfun2 has the ability to store the address of the test function?
void (*pfun1)();
void *pfun2();
void (*pfun1)();//Combined with * first, it is a pointer, () indicates that it points to a function, and void indicates the return value of the function.
void *pfun2();//First combined with (), it is the declaration of the function, and the return value is void *.
int Add(int x,int y)
{
	return x + y;
}

//Define function pointer
int (*p)(int, int)=Add;
//Also
int (*p)(int, int)=&Add;

//Calling a function with a pointer
int ret = p(3, 4);
int ret = (*p)(3, 4);

Two interesting pieces of code

//Code 1
(*(void (*)())0)();
//  void (*) () is a function pointer type. The function has no return value and no parameters
//First, cast the type of integer 0 into a function pointer. At this time, 0 is a function pointer, storing the address of the function, then dereference 0, and then () call the function. The called function has no parameters
//So this code is a function call

//Code 2
void (*signal(int , void(*)(int)))(int);
//First, signal is combined with (). It is a function. There are two parameters of the function, one is int and the other is void(*)(int). Since it is a function, it should have a return type
//After removing signal (int, void(*)(int)), the return type of the function is void(*)(int), which is a function pointer. The return type of the function is null and the parameter is null.
//So a statement is essentially a function declaration
//The function name is signal

The function pointer type looks complex and inconvenient to use. We can use typedef to define an alias

//We know
typedef int DataType;
//Similar definition
typedef void(* pfun )(int);
//pfun is the type alias
//We can use directly to define function pointer variables
pfun pAdd = &Add;

//Similarly, the above void (* signal (int, void (*) (int)) (int); simplify
pfun signal(int, pfun);

5, Function pointer array

Similar to the pointer array, storing the address of the function into an array is called the function pointer array. How to define the array of function pointers?

First, it is an array, which must be combined with the subscript operator [] first, and then the function pointer type

int (* arr[10])(int, int);
//The array has ten elements. Each element type is an int (*)(int, int) function pointer. The return type of the function is int and has two parameters, both of which are of type int.

Application of function pointer array -- transfer table

Transfer table
That is, put the functions with the same return type, number of parameters and type in an array, and then use the array to call each function in different cases.
For example, define four functions: addition, subtraction, multiplication and division. Their return types, number of parameters and types are the same. Put them in an array.

int (* arr[4])(int, int)={add, sub, mul, div };
//call
int ret = (*p[input])(x, y);

6, Pointer to array of function pointers

The pointer to the array of function pointers is a pointer. The pointer points to an array, and the elements of the array are function pointers.

definition
First, it is a pointer, first combined with * - (* parr), and then combined with [], indicating that it points to an array - (* parr)[4], and then the element type of the array - function pointer int (*) (int, int)

int (*(*parr)[4])(int, int) = &arr;

7, Callback function

definition

A callback function is a function called through a function pointer. If you pass the pointer (address) of a function as a parameter to another function, when the pointer is used to call the function it points to, we say it is a callback function. The callback function is not called directly by the implementer of the function, but by another party when a specific event or condition occurs, which is used to respond to the event or condition.

#include<stdio.h>

int Add(int x, int y)
{
	return x + y;
}

int Sub(int x, int y)
{
	return x - y;
}
void test(int (*pfun)(int, int))
{
	int ret = pfun(3, 4);//Call other functions through function pointers
	printf("%d\n", ret);
}
int main()
{
	test(Add);//Take the address of the function as an argument
	test(Sub);
	return 0;
}

summary

Pointer is a major feature and difficulty of C language. It can be unlimited. We need to deeply understand their properties in order to learn and use it.

I hope it can help you understand the pointer in depth!

Keywords: C

Added by 10legit10quit on Mon, 11 Oct 2021 22:13:56 +0300