Advanced C language pointers (1)

Insert image description here
Hello everyone, today we will share advanced pointers in C language.

Table of contents

1. Character pointer
2. Array pointer
3. Pointer array
4. Array parameter passing and pointer parameter passing
5. Function pointer

1. Character pointer
Among the types of pointers, we know that there is a pointer type called character pointer char *

[See the code below]

int main()
{
    
    
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}

The char pointer pc we defined stores the address of ch, and in ch we store the character 'w', so we can get *pc='w' by dereferencing pc.

Next we see the following example:

int main()
{
    
    
const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
printf("%s\n", pstr);
return 0;
}

Insert image description here
Here we put the address of the first letter of the string into the pointer. When we print the string, we only need to use %s to print it out.

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

So let’s guess whether the results of this question will be the same?
Insert image description here

Insert image description here
We see that the results of the two arrays str1 and str2 are different because these two arrays have applied for two relatively independent memory areas, so our two arrays are different, and the pointers in str3 and str4, What is stored inside is the address of the first letter of the string, and since the stored addresses are the same, our system defaults to the two pointers being the same.

2. Pointer array
A pointer array is an array that stores pointers.

Next we 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;
	for (i = 0; i < 3; i++)
	{
    
    
		int j = 0;
		for (j = 0; j < 5; j++)
		{
    
    
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

Because when our pointer points to the array name, it points to the address of the first element of the array. Here we get the addresses of the first elements of the arr1, arr2 and arr3 arrays to print the elements of the entire array, so we only need to use loop nesting next. Simulate three arrays into a two-dimensional array.
Insert image description here
We review the array name here to facilitate our next study:
the array name is the address of the first element of the array
, but there are 2 exceptions:

  1. sizeof(array name), the array name here represents the entire array, sizeof(array name) calculates the size of the entire array, the unit is bytes
  2. &Array name, the array name here represents the entire array, and the address of the array is taken out.
int main()
{
    
    
	int arr[10];
	printf("%p\n", arr);//int*
	printf("%p\n", arr+1);

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

	printf("%p\n", &arr);//
	printf("%p\n", &arr+1);

	//指针类型决定了指针+1,到底+几个字节

	return 0;
}

Insert image description here

We found that the addresses of the first, third, and fifth are all the same, so we know that the address of the array name is the address of the first letter of the array, and the addresses of the second and fourth are the same. So we can get that there are many ways for us to print array elements. In the last one, we add 1 to the entire array. The difference between the addresses of the last two is 40 bytes, so we can also know that it skipped an array.
After seeing this, I believe everyone has a deeper understanding of array names.

int main()
{
    
    
	//指针数组
	char* arr[5] = {
    
    "hello bit", "hehe", "penggeC", "bitejiuyeke", "C++"};

	int i = 0;
	for (i = 0; i < 5; i++)
	{
    
    
		printf("%s\n", arr[i]);
	}

	return 0;
}

Because we know that the pointer points to the address of the first letter of the string, we can use this first address and %s to print out the entire string, so we can then use a loop to print the entire array.

Insert image description here

3. Array pointer
An array pointer is a pointer.

Let us distinguish which of the following is an array pointer?

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
int main()
{
    
    
	int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", p[i]);
	}
	return 0}

Insert image description here
Seeing this code block, we use the pointer to get the address of the array name, which is actually the address of the array. Then the pointer *p points to the address of the array. Next, we use a loop to print the array in sequence to print out the array. However, this is not the only printing method. After learning about array pointers, we can use pointers to replace array names. See the following code:

int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
int (*p)[10] = &arr;

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

Insert image description here
We can use this method to print the array in the future, but we have to ensure that the *p pointer is enclosed in (), because [] has a higher priority than (), so we use () to ensure that *p combine.

void print_arr2(int (*arr)[5], int row, int col)
{
    
    
int i = 0;
for(i=0; i<row; i++)
{
    
    
for(j=0; j<col; j++)
{
    
    
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
    
    
int arr[3][5] = {
    
    1,2,3,4,5,6,7,8,9,10};
print_arr1(arr, 3, 5);
//数组名arr,表示首元素的地址
//但是二维数组的首元素是二维数组的第一行
//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
//可以数组指针来接收
print_arr2(arr, 3, 5);
return 0;
}

We use the array pointer to receive this two-dimensional array arr. The address we pass is the first address of the two-dimensional array, which is the address of the first row of the two-dimensional array, which is the address of a one-dimensional array.

4. Array parameters and pointer parameters

Next let's pass the parameters of the one-dimensional array:

#include <stdio.h>
1 void test(int arr[])//ok?
{
    
    }
2 void test(int arr[10])//ok?
{
    
    }
3 void test(int *arr)//ok?
{
    
    }
4 void test2(int *arr[20])//ok?
{
    
    }
5 void test2(int **arr)//ok?
{
    
    }
int main()
{
    
    
int arr[10] = {
    
    0};
int *arr2[20] = {
    
    0};
test(arr);
test2(arr2);
}

When passing parameters through arrays, the formal parameters can be written in the form of arrays. The essence of passing parameters through arrays is to pass the address of the first element of the array, and the passing parameters through arrays can also be in the form of pointers. The above five parameters are all correct. See the last one
. It is found that a second-level pointer is used. That is because the address of the first-level pointer is stored in our second-level pointer, so the fifth parameter is also correct.

Passing parameters of two-dimensional array:

1 void test(int arr[3][5])//ok?
{
    
    }
2 void test(int arr[][])//ok?
{
    
    }
3 void test(int arr[][5])//ok?
{
    
    }
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
4 void test(int *arr)//ok?
{
    
    }
5 void test(int* arr[5])//ok?
{
    
    }
6 void test(int (*arr)[5])//ok?
{
    
    }
7 void test(int **arr)//ok?
{
    
    }
int main()
{
    
    
int arr[3][5] = {
    
    0};
test(arr);
}

When we pass parameters in a two-dimensional array, the rows can be omitted but the columns cannot be omitted. Because we are passing parameters in a two-dimensional array, we must either use the form of a two-dimensional array for the formal parameters, or use the form of an array pointer to pass them. Parameters, see that the sixth one we use is the array pointer, which stores the address of the first row of the two-dimensional array, so we can use the array pointer to complete the parameter transfer, so only 1, 3, and 6 can successfully transfer the parameters. .

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

Here we just need to simply write the formal parameters as a one-dimensional array. So when the parameter part of a function is a first-level pointer, what parameters can the function receive? Any of the following are available.
Insert image description here
Secondary 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;
}

When passing parameters via a secondary pointer, we can just use the secondary pointer to accept it. So when the parameter of the function is a secondary pointer, what parameters can be received?
Insert image description here
These are acceptable parameters.

5. Function pointer

Let us first see the following piece of code:

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

Insert image description here

We found that the two printed addresses are the same, so we can know that the address of the function is stored in the pointer. So what if we want to save the address of the function?

void test()
{
    
    
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);

We need to use pointers to save addresses, so which one is the pointer? 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.

After such sharing, everyone should have mastered what they have learned. Today we will simply study here. Thank you all!

Guess you like

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