指针功能强大,但如果使用不当,也是一个重大隐患。
为了深入理解指针,需要了解指针在不同的场合有不同的应用场景。
先看思维导图:
这里的对象是指内存对象,数据存储在内存中的数据对象。
1.1 指针指向普通变量
demo:
int main()
{
int i = 100;
int *p;
p = &i; // 指针指向普通变量
printf("己值与他值:%x = %x
",p,&i);
}
1.2 指针指向对象
demo:
class Point{
int x,y;
public:
Point(int a,int b):x(a),y(b){};
};
int main()
{
Point p1(100,100);
Point *pt = &p1; // 指针指向对象
}
1.3 指针指向对象的数据成员
demo:
class Point{
public:
int x,y;
Point(int a,int b):x(a),y(b){};
};
int main()
{
Point p1(4,5);
int *p = &p1.x; // 指针指向对象的数据成员
}
1.4 类的数据成员指针
demo:
#include
using namespace std;
class Point{
public:
int x,y;
Point(int a,int b):x(a),y(b){};
};
int main()
{
Point p1(4,5),p2(7,8);
int Point::*p; // 类的数据成员指针,声明时需要类名限定
p = &Point::x;
cout<
数组名是一个特殊的指针,首先是做为元素的基址,具有常量性质,然后是在不同的上下文中,具有不同的目标类型:
上下文一:数组名的目标类型是整个数组(当与操作符&、sizeof一起使用时),值为首元素地址;
上下文二:数组名的目标类型是数组元素类型(不与操作符&、sizeof一起使用的其它场合),值为首元素地址;
2.1 指针指向数组元素
demo:
int main()
{
int a[10];
int *p;
int i = sizeof a; // a表示整个数组
int (*ap)[10] = &a; // a表示整个数组
p = a; // 指针指向数组元素,此时的a就相当于&a[0]
}
数组名的类型转变为元素类型指针(降一维的处理,一维数组的元素类型指针是int*),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。
2.2 指向数组的指针
int main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p2)[3][4] = &a; // p2与a的目标类型为int[3][4]
int (*p)[4] = a; // 指向数组的指针,p的目标类型为int[4]
}
数组名的类型转变为元素类型指针(降一维的处理,二维数组a的元素类型指针是int(*)[4],元素类型,也就是指针的目标类型是int[]),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。
2.3 指针数组
#include // 定义了NULL
int main()
{
int x=2,y=3;
int a[3] = {89,72,43};
int *p[4]={&x,&y,NULL,a}; // 指针数组
int **q = p; // 指针数组名可以赋值给一个二维指针,
// 因为一维数组名是一个一级指针,而指针数组的元素也是一个一个一级指针
}
3.1 函数指针:指向函数的指针
demo:
int f(int,int){return 0;}
int main()
{
int(*p)(int,int); // 函数指针:指向函数的指针
p=f;
}
3.2 类成员函数指针
demo:
#include
using namespace std;
class Point{
int x,y;
public:
Point(int a,int b):x(a),y(b){};
int getX()const;
int getY()const;
};
int Point::getX()const{return x;}
int Point::getY()const{return y;}
int main()
{
Point p1(4,5),p2(7,8);
int(Point::*funcPtr)()const; // 类成员函数指针,声明时需要类限定
funcPtr = &Point::getX;
cout<<(p1.*funcPtr)()<
3.3 函数的参数为指针
demo:
int f(int arr[],int n){return 0;} // 所谓的数组写法,实质也是一个指针
int g(int*x,int n){return 0;}
int main()
{
int arr[10];
f(arr,10); // 被调函数形参:数组,主调函数实参:数组
int*p = arr;
f(p,10); // 被调函数形参:数组,主调函数实参:指针
g(arr,10); // 被调函数形参:指针,主调函数实参:数组
g(p,10); // 被调函数形参:指针,主调函数实参:指针
}
3.4 指针函数:指针类型函数
demo:
#include
int*func(int x,int y) // 指针函数:指针类型函数
{
int *q = (int*)malloc(sizeof(int));
*q = x*y;
return q;
}
int main()
{
int *p=func(2,3);
free(p);
}
4.1 指针的指针
demo:
#include
int main()
{
int a=100;
int *p = &a;
int* *p1 = &p; // p1是一个指针,指针的元素是一个一级指针int*,所以p1是一个二级指针
std::cout<<(*p1 == p)<
4.2 指向数组的指针
demo:
int main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4] = a; // 指向数组的指针,p的目标类型为int[4]
}
数组名的类型转变为元素类型指针(降一维的处理,二维数组a的元素类型指针是int(*)[4],元素类型,也就是指针的目标类型是int[]),是因为数组的操作主要是元素的操作,元素的操作在于元素地址的取得(基址+偏移),由元素类型可以确定偏移的步长。
首先是指针(*p),然后元素类型是int[4],结合到一起就是int (*p)[4]。
4.3 指针数组
#include // 定义了NULL
int main()
{
int x=2,y=3;
int a[3] = {89,72,43};
int *p[4]={&x,&y,NULL,a}; // 指针数组
int **q = p; // 指针数组名可以赋值给一个二维指针,
// 因为一维数组名是一个一级指针,而指针数组的元素也是一个一个一级指针
}
首先是指针(*q),然后元素类型是int*,结合到一起就是int**q。
指针构造了数据(变量)之间的一种联系,涉及到己型、己址、己值,他型、他址、他值,当用const修饰指针变量时,const可以修饰他型,也可能修饰己型,或者同时修饰他型、己型。
Syntax | meaning |
const T* | pointer to constant object |
T const* | pointer to constant object |
T* const | constant pointer to object |
const T* const | constant pointer to constant object |
T const* const | constant pointer to constant object |
(区分的关键点在于const位于指针声明符*的前面,则表示const修饰指针的目标类型,表示目标类型不能通过指针去修改,如果const位于指针声明符*的后面,表示修饰自身为常量。)
5.1 指针指向的目标类型为const
表示目标类型的值不能通常此指针去修饰,但并不意味着目标类型是常量类型,如果目标类型本身非const类型,目标类型仍然可以通过自己做左值去修改自身。
demo:
int main()
{
const int a = 20;
const int *p1 = &a; //const位于符号*前,表示修饰目标对象
// 表示目标对象不能通过该指针去修改,
// *p1 = 1; // error,target type is const
// can't modify target with p1;
int b = 30;
p1 = &b;
// *p1 = 1; // error
b=2; // 但如果目标对象是非常量,自身是可以修改的
}
5.2 const指针
demo:
int main()
{
int a,b;
int *const p = &a;// const指针,const位于符号*的后面,表示修饰指针自身
// p = &b; //error
a = 20;
*p=100;
}
5.3 目标类型和己型都是const
int main()
{
int a,b;
const int /*const*/ * const p = &a;
// *p = 12; // error,因为目标类型int被const修饰,表示不能通过此指针去修改
a = 12;
// p = &b; // p被const修饰(const位于符号*之后),表示p本身是一个常量
b=13;
}
5.4 二级指针与const
int main()
{
int a,b;
int *p = &a;
int* const* pp = &p; // non-const pointer to const pointer to non-const int
int *q = &b;
pp = &q;
**pp = 22;
// *pp = &a; // 不能通过pp来修改*pp
const int *r = &a;
int const **qq = &r;
// **qq = 33;
*qq = &b;
const int *s = &b;
qq = &s;
}
通常称void*与泛型指针,是一种类型暂定的指针。void*在一个库函数中使用较多,如malloc的返回值类型,qsort()的参数类型。
code demo:
#include
int main()
{
void *vp;
int arr[] = {1,2,3,4,5,6};
vp = arr; // ① 取得基准地址
// ② vp解引用和算术运算前需要先转型(确定具体类型)
*((int*)vp) = 11;
int *p = ((int*)vp)+1;
*p = 22;
*((int*)vp+2) = 33;
for(int i=0;i<6;i++)
printf("%d ",*((int*)vp+i));
getchar();
}
-End-
页面更新:2024-03-07
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号