C language study notes---Advanced pointers 01

C language pointer advanced part 1

Preface:
What are pointers?
A pointer is an object in a programming language whose value, using an address, points directly to a value stored in another location in the computer's memory.
Since the required variable unit can be found via the address , it can be said that the address points to this variable unit . Therefore, the address that is visualized is called a "pointer"
, that is, the memory unit with it as the address can be found through it.
In addition, the pointer mentioned in normal spoken language usually refers to the pointer variable , which is a variable used to store the memory address. .

/ Summary of knowledge points /

1. A pointer variable is a variable used to store an address. The address uniquely identifies a memory space.
2. The size of the pointer is fixed at 4/8 bytes (32 bits/64 bits).
3. Pointers have types. Pointers have types. The type determines the step size of the pointer ± integer, as well as the permission of pointer dereference.
4. Pointer operations (pointer plus or minus integer: offset; pointer minus pointer: the number of elements between the pointer and the pointer; pointer relationship Operation: pointer size comparison)
For details, see: Pointer Basics

1. Character pointer

Pointers are addresses. Pointers in spoken language refer to pointer variables
. Integer pointers: pointers to integer data.
Character pointers: pointer variables to character data.

#include <stdio.h>
int main()
{
    
    
	char ch = 'w';
	char* pc = &ch;

	char* p = "abcdef";//这里的字符串等价于表达式,然后返回的结果是第一个字符的地址(可理解为数组)
	//注意的是,这里的“abcdef”属于常量表达式,不可改变
	printf("%c\n","abcdef"[3]);//d
	//类似于数组名 --- “abcdef” ,所以可理解为数组形式

	const* pd = "abccdef";

	printf("%s\n", pd);//abcdef
	printf("%c\n", *pd);//a

	return 0;
}

Note that :
(1), the string here is equivalent to the expression, and the returned result is the address of the first character (can be understood as an array)
(2), "abcdef" here is a constant expression and cannot be Change

Example question :

#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("1 to 2 same\n");
	}
	else
	{
    
    
		printf("1 to 2 not same\n");
	}

	if (str3 == str4)
	{
    
    
		printf("3 to 4 same\n");
	}
	else
	{
    
    
		printf("3 to 4 not same\n");
	}

	if (&str3 == &str4)
	{
    
    
		printf("&3 to &4 same\n");
	}
	else
	{
    
    
		printf("&3 to &4 not same\n");
	}
	return 0;
}

Summary :
(1), str1 and str2 are two different space addresses, so they are not equal.
(2), str3 and str4 store the same constant expression, so the addresses they point to are the same, and the values ​​obtained are the same; But the addresses of str3 and str4 themselves are different.

2. Pointer array

Character array – an array that stores characters.
Integer array – an array that stores integers.
Pointer array – an array that stores pointers. The elements stored in the array are pointer types.

For example:
int* arr[5];
char* ch[6];

2.1. Pointer array routine 1 – simulate a two-dimensional array

#include <stdio.h>
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;
}

2.2. Pointer array routine 2

#include <stdio.h>
int main()
{
    
    
	//指针数组
	char* arr[5] = {
    
    "hello bit","hehe","abcf","cojag","waofrdf"};
	int i = 0;
	for (i = 0; i < 5; i++)
	{
    
    
		printf("%s\n",arr[i]);
	}
	return 0;
}

3. Array pointer

Pointer array - is an array, is an array that stores pointers. Array
pointer - is a pointer.
Character pointer - is a pointer to a character. Integer pointer - a pointer to an integer.
Floating
pointer - a pointer to a floating point number.

3.1. Review array names?

The array name is the address of the first element of the array, but there are two exceptions, sizeof (array name), & array name; the
array names of the two exceptions express the address of the entire array.

Array pointer - &arr
is the same as the address value of the first element, but when performing pointer operations, it is found that the size of the entire array is added or subtracted by bytes. At the same time, the pointer
type determines how many bytes (step size) the pointer + 1 +

#include <stdio.h>
int main()
{
    
    
	int arr[10];
	printf("%p\n",arr);
	printf("%p\n",arr+1);

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

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

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

3.2. Array pointer definition and initialization (format)

#include <stdio.h>
int main()
{
    
    
	int arr[10] = {
    
     0 };
	//int* p = &arr;
	int(*p)[10] = &arr;//p是用来存放数组的地址的,p就是数组指针
	
	char* arr2[5];
	char* (*pc)[5] = &arr2;
	//(*pc)说明pc是一个指针类型,(*pc)[5],表示数组指针,char* 表示该数组类型属于字符指针类型
	
	//int arr3[] = { 1,2,3 };
	//int(*p3)[] = &arr3;
	//数组指针的[]操作符的参数必须指明,否则报错
	return 0;
}

3.3. The role of array pointers—commonly used in two-dimensional arrays

#include <stdio.h>
int main()
{
    
    
	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]);
	}
	//指针变量
	int* p = &arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", p[i]);
	}
	return 0;
}

3.4. Array pointer - application of two-dimensional array

The array name of a two-dimensional array is the address of the first element, that is: the address of the first element of the array pointer is the address of the first row

#include <stdio.h>
//二维数组传参也是二维数组的形式
//void print(int arr[3][5], int row, int col)//形参是数组形式
//{
    
    
//	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");
//	}
//}
void print(int (*p)[5], int row, int col)//形参是指针形式,指向第一行
{
    
    
	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},{
    
    6,7,8,9,10} };
	print(arr,3,5);//二维数组传参,行,列
	return 0;
}

4. Exploration of array parameters—pointer parameters as parameters

4.1. One-dimensional array parameter transfer

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

4.2. Two-dimensional array parameter transfer

#include <stdio.h>

void test(int arr[3][5])//ok
{
    
    }
void test(int arr[][])//No,列不可以省
{
    
    }
void test(int arr[][5])//ok
{
    
    }
void test(int *arr)//No,不能以一维数组接收二维数组,因为二维数组的首元素地址是第一行的地址,而不是第一个元素的地址
{
    
    }
void test(int* arr[5])//No,类型不同,int* 与int
{
    
    }
void test(int (*arr)[5])//ok,数组指针,指向第一行
{
    
    }
void test(int **arr)//No,二级指针用于指向一级指针的地址
{
    
    }

int main()
{
    
    
	int arr[3][5];
	test(arr);
	return 0;
}

4.3. Pointer parameter passing

First-level pointer parameter passing :
When passing first-level pointer parameters, the formal parameter is written in the form of a first-level pointer.

#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,10 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//一级指针p传给函数,作形参
	print(p,sz);
	return 0;
}

Thinking expansion 1 :
When we encounter a function whose formal parameter is a first-level pointer, consider what can be passed as the actual parameter of the function?
Answer: As long as it is an address/first-level pointer variable of the corresponding type that can be passed, it is ok, as is the array name.

Second-level pointer parameter transfer :
When the second-level pointer parameter is passed, the formal parameter is written in the form of a second-level pointer.

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

Thinking expansion 2 :
When we encounter a function whose formal parameter is a first-level pointer, consider what can be passed as the actual parameter of the function?
Answer: As long as it is the first-level pointer address/secondary pointer variable of the corresponding type that can be passed, it is OK, and the array name of the first-level pointer type is also OK.

5. Function pointer

Array pointer – pointer to an array – stores the address of the array – & the array name is the address of the entire array
Function pointer – pointer to a function – stores the address of the function

How to get the address of the function? Is it also through & function name?
Answer: Just add the & operator and the function name

5.1. Function pointer initialization (format)

#include <stdio.h>

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

int main()
{
    
    
	//&函数名就是函数的地址
	//函数名也是函数的地址
	printf("%p\n", &Add);
	printf("%p\n", Add);
	//均表示函数的地址

	//函数指针
	//int (*pf1)(int , int) = Add;//pf1就是函数指针变量
	int (*pf2)(int, int) = &Add;//pf2同样是函数指针变量

	int ret = (*pf2)(2, 3);
	//因为Add与&Add等价
	//常规写法:
	//int ret = Add(2,3);
	//所以*号就可以省略
	//int ret = pf2(2,3)
	printf("%d\n",ret);
}

6. Consolidate knowledge points

6.1. Explain the following code 1

int arr[5];//arr是一个存放5个整型数据的数组
int* parr1[10];//parr1是一个数组,数组的10个元素类型是int*
int(*parr2)[10];//parr2是一个数组指针,该指针指向的数组,指向数组的10个元素类型是int
int(*parr3[10])[5];//parr3是一个数组,是存放数组指针的10元素的数组,存放的这个数组指针,指针指向的5个元素是int类型

6.2. Explain the following code 2

#include <stdio.h>
int main()
{
    
    
	(*(void(*)())0)();
	//整体是一个函数调用
	//(void(*)()函数指针类型
	//(void(*)()) 强制类型转换为函数指针类型
	//(*(类型)0)(); --- 所以这段代码表示:
	//调用0地址处的函数,这个函数没有参数,且返回值类型为void省略不写
	
	void (*signal(int, void(*)(int)))(int);
	//整体是一个函数声明
	//void(*)(int)函数指针作为参数
	//signal(int, void(*)(int)) --- 函数,一个参数是int类型,一个参数是函数指针类型,返回值类型也是作为函数指针类型
	//(*signal(int, void(*)(int))) --- 函数指针
	//(*signal(int, void(*)(int)))(int) --- 函数指针参数是一个int类型参数
	//void (*signal(int, void(*)(int)))(int) -- 一个返回值类型为空,参数是一个整型的函数指针的声明
	//所以这段代码表示:
	//是一个函数声明,声明的是signal函数,signal函数的参数有两个,一个是int类型,一个是函数指针类型,该类型是void(*)(int),该函数指针指向的函数,参数类型是int类型,返回值类型为void
	//signal函数的返回值类型也是函数指针类型,该类型是void (*)(int),该函数指针指向的函数,参数类型是int类型,返回值类型为void
	
	//利用typedef 对这段代码简化:
	typedef void(*pfun_t)(int);
	//typedef 对函数指针类型重命名时,被重名的变量名,放在*面,即pfun_t的位置
	pfun_t signal(int, pfun_t);
	return 0;
}

7. Conclusion

This concludes the first part of C language pointer advancement!
To be continued... As soon
as half an acre of sugar cubes are opened, the skylight and cloud shadows linger together.
Ask where the canal can be so clear? Because there is a source of living water. -Zhu Xi (feelings after reading the book)

Guess you like

Origin blog.csdn.net/m0_69455439/article/details/132501166