C++篇:第六章_指针_知识点大全
C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器
六、指针
(一)指针规则
-
两个指针不能进行加法运算,因为指针是变量,其值是另一个变量的地址,故两地址相加没意义,但可以用一个空指针赋值给某个指针变量,值为NULL
-
如果两个指针是指向同一类型的两个指针,则两个指针之间可以进行相减(实际是所指向对象的相减)和关系、运算
-
无论任何指针在32位系统中是4字节 64位系统中是8字节
-
初始化为NULL的类指针,可以安全的调用不涉及类成员变量的类成员函数而不会出错
-
初始化指针时所创建的字符串常量被定义为只读。如果试图通过指针修改这个字符串的值,程序就会出现未定义的行为,例:char* s="AAA";
-
指针本身存于栈中
-
当free释放内存之后,指针还指向原来的那块地址,需要我们设置 p = NULL;如果不手动设置 p = NULL,此时P就变成了野指针;野指针产生原因:
-
声明的指针未被初始化,指针默认值随机产生。创建指针应该将其初始化为NULL或者指向某一内存。
-
free和delete掉的指针未重置为NULL,free后的指针仍指向该内存,但该内存已变为垃圾内存。
-
空指针(值为0)不指向任何实际的对象或函数,反过来说对象或函数的指针也不可能为空指针
-
C++的指针有数据指针,函数指针,数据成员指针,成员函数指针四种,后两种是C++专门为类扩展的称为成员指针
-
不要试图通过改变形参指针变量的值而使实参指针变量的值改变,因为实参变量和形参变量之间的数据传递是单向的
当实参是地址(如&a),传递的是地址,则仍然是传值方式,当实参是变量名,而传值的是变量的地址,才是传址方式
- 在使用一个指针之前,必须先赋初始值
(二)指针使用
-
如果p=&a,p+4指的是p的值+4,也就是a+4(ASCALL码+4),因此为e;(p+4)指的是首地址后移4位再取值
-
int &i; /没有这种语法/ int &i; /没有这种语法/
3. 定义:
① void f() ; // 无返回值
② void* f(); // 返回一个无类型指针
③ int (p[10])(int) // 定义了一个指针数组,数组元素都是int (*p)(int *)的函数指针,所以p是一个函数指针数组
④ 64 位情况下:
(1) char ** p[4] // 表示char**数组返回 4 * 8 = 32
(2) char * (* p)[4] // 表示指向 char* 数组的指针返回8
(3) char (**p)[4] // 表示指向 char数组的指针的指针返回8
⑤ 指针前加&是什么意思
(1) 在定义时使用,如
int *a;
int * &p = a;
这种是C++中的引用(引用全部是const类型),p本身不占用内存空间,只是a的一个别名,对p的访问完全等同于对a的访问。
(2) 在非定义时,指针前加&表示取指针的地址。如
int * a;
int **p = &a;
这里a本身是指针变量,每个变量都有自己的内存空间,对变量做&操作,可以取得这个空间的首地址。于是&a就是取a的地址赋值给p,这样,*p就等同于a
⑥ 函数指针:void (*f)(); // 声明一个指针,指向void x()类型函数,定义函数指针需要打括号
(1) 函数指针所指向的函数,返回值类型,形参列表必须完全匹配
⑦ char (*p)[16]:p是指向长度为16的字符数组的指针(括号中有指针表示,这个变量就是指针类型)
⑧ char p[16]:由于[ ]比优先级高,因此p先与[4]结合,形成p[4]的数组的形式。然后与p前面的“ * ”结合,“ * ”表示此数组是指针类型的,故为指针数组
-
指针和void*可以相互转化(结合笔记P28void型指针)
-
文件指针指向的是一块内存区域,这块区域存储着打开的文件的相关信息,包括文件读取指针当前位置、文件读取缓冲区大小等信息,并不是指向文件的。fscanf是从文件中格式化读取,fprintf才是向文件中格式化写入
-
指针允许0值常量表达式,例:int *P;P=0;
(三)const与指针
-
口诀:左定值,右定向。 const在的左边不能改变字符串常量的值;const在的右边不能改变指针的指向
-
把一个const对象的地址赋给一个非const对象的指针变量是错误的,但反之可以
-
int const p // 类型为int const,此时为常指针其指向不能改变
const intp // 类型为const int,此时为指向常量的指针变量,不能通过P修改其指向的对象的值
(四)数组与指针
- int a[ ] = { 2,4,6,8 },*p=a;(注意与上面的二维数组进行区分)
- 数组名为常量指针,只能在定义是初始化,不可把其当作普通指针单独赋值或出现在左值和某些算术运算中,只有作为参数传递时才退化为普通指针
- 两个指针指向同一个数组的元素则可以进行比较,不指向同一数组则比较是无意义的
- *(a+1)[5] 这种表示不正确,因为就像int a[5];声明一个长度为5的int类型数组。这里,a[5]只是一种声明的写法,这里声明的变量是a,不是a[5]
(五)函数与指针
- Int (*P)(int a); // 定义函数指针变量;可以将函数的地址(函数名)赋值给函数指针变量。但要求函数指针变量与指向函数必须有相同的返回类型、参数个数、参数类型
(六)结构体与指针
-
想访问用new 所开辟的结构体空间,无法直接通过变量名进行,只能通过指针进行访问
-
如果要建立一个动态链表,必须从第1个结点开始,逐个的开辟结点并输入各结点数据,通过指针建立起前后相连的关系