We have already touched on the topic of pointers in the "Pointers" chapter at the primary stage. We know the concept of pointers:1. A pointer is a variable, used to store addresses. The address uniquely identifies a memory space.2. The size of the finger is fixed 4/8 Special value ( Iheidai). /64Iheidai 323. Pointers have types, and the type of the pointer determines the pointer's +- integer Step size, permission during pointer dereference operation.4. Pointer operations.5. Memory units are numbered, number == address == pointer
Next we will learn more advanced content about pointers.
Table of contents
3.1 Definition of array pointer
4. Array parameters, pointer parameters
4.1 One-dimensional array parameter transfer
4.3 First-level pointer parameter passing
4.4 Second-level pointer parameter passing
Read two interesting pieces of code:
1. character fingertip
Among the types of pointers, we know that there is a pointer type called character pointer char* ;
int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
int main()
{
const char* pstr = "abcdef";//这里是把一个字符串放到pstr指针变量里了吗?
printf("%s\n", pstr);
return 0;
}
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";
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;
}
2. Finger combination
An array of pointers is an array in which each element is a pointer. Each pointer can point to different types of data or objects.
Like the following form:
int* arr1[10]; //整形指针的数组
char *arr2[4]; //一级字符指针的数组
char **arr3[5];//二级字符指针的数组
You can use an array of pointers to simulate a two-dimensional array:
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
//int* int* int*
//指针数组
int* arr[] = { arr1, arr2, arr3 };
int i = 0;
return 0;
}
、
Int* arr[] stores three elements arr1, arr2, and arr3, and the type of each element is int*.
Of course, this way of writing can be accessed like a two-dimensional array:
You can also maintain multiple strings this way:
int main()
{
//指针数组
char* arr[5] = {"hello", "hehe", "haha", "heihei", "C"};
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
Running results and illustrations:
3. Number of fingers
3.1 Definition of array pointer
Are array pointers pointers? Or an array?The answer is: pointers.We are already familiar with:Integer pointer: int * pint ; A pointer that can point to integer data.Floating point pointer: float * pf ; A pointer that can point to floating point data.The array pointer should be: a pointer that can point to the array.
Which of the following codes is an array pointer?
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
int ( * p )[ 10 ];Explanation: p is first combined with *, indicating that p is a pointer variable, and then points to an array of 10 integers. So p is a pointer, pointing to an array, called an array pointer.Note here: [] has a higher priority than *, so () must be added to ensure that p is combined with * first.
3.2 &number group nameVSnumber group name
int arr[10];
arr sum &arr separation is it?We know that arr is the array name, and the array name represents the address of the first element of the array.Then &arr What is the name of the array?
Let's look at a piece of code:
#include <stdio.h>
int main()
{
int arr[10] = {0};
printf("%p\n", arr);
printf("%p\n", &arr);
return 0;
}
#include <stdio.h>
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, &arr and arr< a i=4>, although the value is the same, the meaning should be different.Actually: &arr represents the address of the array , rather than the address of the first element of the array. (Experience it carefully)In this example &arr the type is: int(*)[10] < /span> , is an array pointer typeThe address of the array +1 , skipping the entire array size, so &arr+ The difference between 1 and &arr is 40. a>
3.3 Use of array pointers
int main()
{
int arr[10] = { 0 };
int (*p)[10] = &arr; //p是用来存放数组的地址的,p就是数组指针
char* arr2[5];
char* (*pc)[5] = &arr2;//pc是用来存放数组的地址的,每个数组的类型为char*
int (*p)[10] = &arr;
int arr3[] = { 1,2,3 };
int (*p3)[3] = &arr3;
return 0;
}
In the above code, why not just use int (*p)[10] =arr;?
This is because although the values of arr and &arr are the same, their meanings are different:
*** arr refers to It is the first address of the first element of this array.
*** &arr refers to the first address of this entire array .
void print(int (*p)[5], int r, int c)
{
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
print(arr, 3, 5);
return 0;
}
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
explain:
4. Array parameters, pointer parameters
When writing code, it is inevitable to pass [array] or [pointer] to a function. How should the parameters of the function be designed?
4.1 One-dimensional array parameter passing
#include <stdio.h>
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}
void test2(int** arr)//ok?
{}
int main()
{
int arr[10] = {0};
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
The above writing methods are all OK.
Numeric parameters and formal parameters can be written in array form.
The essence of array parameter passing is to pass the address of the first element of the array.
Array parameters can also be passed in the form of pointers
4.2 Two-dimensional number combination
void test(int arr[3][5])//ok?
{}
void test(int arr[][])//ok?
{}
void test(int arr[][5])//ok?
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//ok? 这是接收一维数组的写法
{}
void test(int* arr[5])//ok?这是指针数组,也不行
{}
void test(int (*arr)[5])//ok?这才是对的,用数组指针
{}
void test(int **arr)//ok?二级指针是用来接收一级指针的,所以也不行
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}
4.3 First-level pointer parameter passing
#include <stdio.h>
void print(int* p, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d\n", *(p + i));
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
//一级指针p,传给函数
print(p, sz);
return 0;
}
Use a first-level pointer to pass parameters, and use a first-level pointer to receive formal parameters.
When the parameter part of a function is a first-level pointer, what parameters can the function receive?
4.4 Second-level pointer parameter passing
#include <stdio.h>
void test(int** ptr)
{
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int* p = &n;
int** pp = &p;
test(pp);
test(&p);
return 0;
}
Secondary pointers are used to pass parameters, and formal parameters can be received using secondary pointers.
When the parameter of a function is a secondary pointer, what parameters can it receive?
5. Function indicator
First of all, it is a pointer, a pointer to a function, and the address of the function is stored in the memory space;
Let’s look at the code first:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
Here we know,&The function name is the address of the function, and the function name is also the address of the function.
The output is two addresses, which are the addresses of the test function.
void test()
{
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();
pfun1 can be stored. pfun1 is first combined with *, indicating that pfun1 is a pointer. The pointer points to a function. The pointed function has no parameters and the return value type is void.
Let’s set up an example: simple summation
int Add(int x, int y)
{
return x + y;
}
int main()
{
int (* pf2)(int, int) = &Add;
int ret = (* pf2)(2, 3);
printf("%d\n", ret);
return 0;
}
operation result:
As a function pointer, pf2 is also an address, and the function itself is also an address, so the * in (* pf2) in int ret = (* pf2)(2, 3) can naturally be omitted. int ret = pf2(2, 3) is also possible.
Read two interesting pieces of code:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
Code 1: void(*)() is a function pointer type, *(void (*)())0 is forced type conversion 0, and 0 is regarded as the function address, then there is void(*)() at the 0 address Such a function, so the meaning of this code is: call the function at address 0. This function has no parameters and the return type is void.
Code 2:
Code2 is too complex, how to simplify it:
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
Typedef it.