学习记录:指针(未整理)

1. 指针是什么?

指针就是内存的地址,指针变量就是能够保存内存地址的变量。

一般数据类型变量名指的是这个数据所代表的值。

2. 如何定义指针?

在最开始声明一个指针变量的时候,为了表明是一个指针变量,要在变量名前加“*”(间接引用符),在后续的使用中则不用加“*”了

下面两种写法是等价的

//一个变量
int a;
//第一种,分开写
int *t;
t=&a
//第二种
int *t=&a

前面的数据类型表明了指针指向的是什么样的数据类型

3. 具体用法

3.1:通过指针剪间接修改变量值

还是用上面的例子,下面两种写法是等价的

a=200;//直接修改
*t=200;//间接修改

其实把*t看作a也行

3.2:指针的初始化

int *t=&a;
//指针类型 *指针变量名 = &变量
//注意指针指向的数据类型要和指针类型一致

3.3:注意事项

指针数据只能使用四种值

1. 0值 常量 表达式

int a,b=0;
int *t=a;//错,不能把整形数据赋给指针变量
int *t=b;//错,b是个变量
int *t=400;//错,非0  
int *t=null;//对,null可以看作0
int *t=0;//对,是0,是个常量

2.  不能指向不同的数据类型

3.  直接将相同类型的指针互相赋值

4. 类似于数组的,在下一个地址处有有效的数据类型的

 

4. 无效的指针类型

1. 0值指针

刚才说过0可以赋值给一个指针变量,但这是无效的

2. 指针未初始化且未赋值时

这种指针很明显是无效的

3. 指针指向的变量的内存空间已经被释放了(迷途指针)

同上

三种类型都是没有指向一个确定的对象,因此无效

 

5.  指针的运算

指针的运算一般只有在连续的储存空间中才有意义(比如数组)

(否则没有指向一个确定的对象,这个指针就是无效的啊)

int x[10],*p=&x[5];
p+1//指向x[5]的后一个int变量
p-1//指向x[5]的前一个int变量
也可以加减一个变量
int n=1;
p+n,p-n都是可以的
自加自减也可以

两个指针可以相减(但是不能相加啊)

指针相减得到的值是这两个指针之间所有对象的个数

也可以比较大小(比较两个地址的大小关系)

 

6. const指针

第一种指针的定义:const 数据类型 *指针名

对于一个常量,我们可以用一个常量指针指向一个常量

(用变量指针编译都过不去)

相同的,一个常量指针也可以指向一个变量

但是,一个变量指针不能指向一个常量

 

一个常量指针也就代表了无法通过指针间接修改它所指向的值

因此一般用于函数,确保在函数中引用的值不会被改变

 

第二种指针 数据类型 const *指针名

它表明了这个指针指向的对象是不会改变的

因此,试图改变它指向的对象的操作都是非法的

但是要分开,这种指针可以间接改变它所指向的值

 

当使用带有const的指针时其实有两种意思。一种指的是你不能修改指针本身的内容,另一种指的是你不能修改指针指向的内容。听起来有点混淆一会放个例子上来就明白了。

 

 

第三种指针 const 数据类型 const *指针名

以此类推,这种指针是一种指向的对象不能够变化,也不能通过指针来修改对象的值的指针

 

 

2.4.  指针与一维数组

一个数组由若干个元素组成,每个元素都有相应的地址,可以用指针来获取每个元素的地址

C++中规定,数组名既代表数组本身,又代表整个数组的地址(所以用scanf输入字符串时不需要加取地址符)

数组名还是一个常量,不能被改变(不能进行赋值,相加相减)

同时,数组名还是数组首元素的地址,因此下面两个语句是等价的

int a[10];
1. int *p=a;
2. int *p=&a[0];

 

如上,我们获得一个指向a数组的指针p

这时我们有四种方法可以访问数组的值

1. a[i]      //通过数组下标访问
2. p[i]      //通过指针下标访问
3. *(a+i)    //通过地址引用访问
4. *(p+i)   //通过引用指针访问

(毕竟a也是一个地址啊,和p里存的是一个东西,可以把p当a用)

 

2.5 指针与字符串

C++允许定义一个字符指针,在初始化时可以直接指向一个字符串常量,比如

1. char *p="C Language";
2. char *p;
  q="C Language";

这时p储存了这个字符串的首地址,而不是整个字符串,这时称p指向字符串

通过字符指针可以访问字符串,如

char str[]="C Language", *p=str;//p指向字符串
cout<<p<<endl;  //输出C Language(因为字符串会一直输出直到'\0')
cout<<&strl[7]<<endl;  //取地址同理,输出age

还可以通过字符指针遍历字符串
while (*p!='\0')
    cout<<*p++;        //这时候*p不是地址,只会一个字符一个字符的输出

2.5.1 指针数组

定义:元素的数据类型时指针的数组称为指针数组,例如

char *name[]={"Lin","Ding","Zhan"};

现在name就是一个字符指针数组

  但是不同于一般数组的是,指针数组中储存的是指针,例子中就有三个指针,分别指向不同的字符串

之前说过数组名也算是一个指针,这里name也是一个指针,是 指向指针的指针,就是 二级指针

声明一个二级指针,和一级指针差不多,不过要用两个星号,如下

char **pname;//指向上例中的name
pname=name;
//如果用二级指针去给一级指针赋值会报错
现在pname指向name[0],pname[1]=name[1];

 2.5.2 指向一维数组的指针

也就是指向二维数组行的指针变量,比如

//对于一个二维数组
int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
//可以用如下格式定义指向行的指针变量
int (*p)[4];//加了括号,后面跟着是数组列的大小
//对这种指针赋值时只能赋行地址
p=a;p=&a[0];
//不能列地址,如
p=a[0],p=&a[0][0];

 

3.1 指针与函数

指针最重要的应用是作为函数参数,它能够将更多的运算结果返回到主函数中

因此,指针是函数传递参数的重要工具

函数形参可以是指针类型,形参直接加个星号(int *p)就行

对于数组(一维或多维)做函数形参,比如

//一维数组为例
double average (double *a, int n)//也可以写double a[]
{
    //函数体
}
//调用时
double x[100],f;
f = average (x,100);
//数组名做指针传入函数中

 

posted @ 2020-02-18 19:48  Salty_Fish  阅读(137)  评论(1编辑  收藏  举报