1.指针
1.1指针所占内存空间(用sizeof(变量名)看)
无论是int*是float*还是double* 只要是32位系统是占四个字节,如果是64位系统是占八个字节。
1.2空指针和野指针
空指针:指针变量指向内存编号为0的空间。空指针用于初始化指针变量。
int *p = NULL; //但是该空指针无法访问,只是为了初始化如果不给就成了野指针。
注意:空指针无法访问,更无法修改 0~255的内存编号是系统本身占用
野指针:指针变量指向非法内存
①局部变量指针未初始化 int* p; //局部变量指针未初始化,默认就是随机值 *p=10; return 0;
②指针访问越界 int arr[10]={0]; int* p=arr; for(int i=0;i<12;i++) { *p++=i; } return 0;
③指针指向的空间释放
如何规避野指针:
1、指针初始化 (如果没有就初始化为NULL)
2、小心指针越界
3、指针指向空间释放即使其置为NULL
4、指针使用之前检查有效性 (例如:判断是否为NULL)
1.3const修饰指针
Const**修饰指针: const int*p =&a,在指针类型前加const称为常量指针;特点:顾名思义,指向常量的指针!**即无论指向的地址上是变量还是常量都认为其是常量。所以常量指针不能更改地址上的值,只能修改指针的指向。如果a是变量怎么修改地址上的值呢?通过a=另一个值。
Const**修饰指针名: int * const p =&a;在指针名前加const称为指针常量;特点:顾名思义,该指针是个常量!**指针不能改变(即指针指向不能改变),但指针内容可以通过指针改变。
Const**修饰指针又修饰指针名:const int * const p =&a;上面两种的结合!
1.4 指针和数组
指针数组:数组名就是数组的首地址
//利用指针访问数组 int arr[10] ={1,2,3,4,5,6,7,8,9,10}; int * p = arr; //别忘了!数组名就是数组的首地址。 cout<<"利用指针访问第一个元素"<<*p; p++;//指针的偏移量为 指针的基础类型,是int占四个字节 ,故指针向后偏四个字节 cout<<"利用指针访问第二个元素"<<*p;
1.5 指针和函数
①为消除值传递的影响,可使用指针进行地址传递(后面引用可以消除)
int fun(int* x,int * y) //传入指针 { return (*x+*y); }
②指针函数:以指针为返回值的函数;返回函数类型若是指针,则可以作为左值(后面引用也可)
int* add(int a,int b) //特别要注意与函数指针的定义差别!!! { int c = a+b; int* p = &c; //指针tmp指向c return p; //返回p指向的地址 }
③函数指针:指向函数的指针。 返回类型 (*函数指针变量名)(形参列表); “它能且仅能指向如下形式的函数” 返回类型 函数名(形式参数列表) { 函数体 }
(1)使用函数指针的一般写法
int (*p)(int a,int b);//定义函数指针变量 //可以指向以下函数 int max(int a,int b); int min(int a, int b); //方式为 int (*p)(int a,int b) = max; int (*p)(int a,int b) = min;//函数指针说白了还是一个指针,但是为了有别于int * p的变量指针 *p必须加括号,另外函数作为右值目前来看也仅仅出现在这里。 //调用方式和函数调用一样 cout<<max(1,2); cout<<p(1,2);
(2)函数指针便捷写法
由于每次定义函数指针写的代码太多所以我们用 typedef在main函数之前定义一个函数指针类型
typedef int(*Function_p)(int, int); int main{ Function_p p1 = max; Function_p p2 = min; }
[函数指针的用途] https://blog.csdn.net/cbb8234078009/article/details/106480972
这个博主文章内有具体例子。
指向函数的指针多用于指向不同的函数,从而可以利用指针变量调用不同函数,相当于将函数调用由静态方式(固定地调用指定函数)变为动态方式(调用哪个函数是由指针值来确定)。熟练掌握函数指针的应用,有利于程序的模块化设计,提高程序的可扩展性。