ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

20.11.21对指针的学习

2020-11-21 23:02:54  阅读:12  来源: 互联网

标签:21 int 指针 地址 数组 new 20.11 变量


这个礼拜都在刷学校的oj啊,,不过基本都是刷熟练度,随笔这东西我还是随性写吧,什么定时总结我还是不适合,不过偶尔的大总结还是可以有的,唉,我这个糟糕的惰性

指针:间接访问


1、指针的概念


1.1、间接访问和直接访问

指针就是地址。
定义一个变量 x ,直接使用这个变量的方式称直接访问,通过指针(地址)间接使用 x 的方式称为间接访问

1.2、指针变量的定义


定义方式如下

int *p;        //int 表示指针 p 保存的地址中储存的是个整型数.
int *p,*q;     //定义两个指针变量 p,q.
int *p,q;      //定义一个指针变量 p 和整型变量 q.

其中,p 才是指针变量,而 *p 是定义的格式,也是后续用来实现间接访问的形式。
指针 p 中储存的是地址,但 p 本身也有自己的地址。

1.2、指针的基操


1.2.1赋值

赋值方法:①直接将某变量的地址付给指针:

int x,*p;   
p=&x;      //&是取地址符
//或者
int x,*p=&x;    //x 要在 p 前定义

②将同类指针变量的值直接赋给另一指针变量,如:

int x,*p=&x,*q=p;       
//或者
int x,*p=&x;
int *q;
q=p;

若不赋初值:

若定义为全局,则指针 p 的值为 0 。

若定义为局部,则为随机值,所以可以给他先赋值符号常量NULL,其值为0,来表示这个指针不指向任何地址。
如:

int *q=NULL;

③不同类型指针间不能赋值

1.2.2指针变量的访问

在定义并赋予初值后,可以通过 p 来取用指针 p 中保存的地址所储存的变量。

运算符是 取指针 指向 的 值 的运算符。

int x,y,*p;
x=3;y=4;
p=&x;

*p=y+4;     //执行该语句后,指针 p 中储存的值还是 x 的地址,但 x 的值被改变为 y+4 的值,也就是 8 。

所以通过 *p 间接引用时,大可可以把它当做它指向的变量 x 。

1.2.3统配指针类型void

如果定义:

void *p;

那么指针 p 可以存放任何类型变量的地址,也可以和任何类型的指针相互赋值。

1.2.4 指针与常量限定符conset

如果按如下方式定义:

const int *p=&x;    //指针变量 p 的值可以修改但不能通过 *p 来修改 p 所指向变量的值. 
int *const p=&x;    //指针 p 的值不能修改但能通过 *p 来修改 p 所指向变量的值.这种方式必须给定初值.其中 p 为指针常量
const int *const p=&x; //指针 p 的值不能修改且不能通过 *p 来修改 p 所指向变量的值。

2、指针运算和数组


2.1、指针运算


地址本质上是一个整数,所以对指针进行算术运算是理所当然的,对指针进行算术运算的过程称为指针运算

指针运算考虑指针的基本类型
如果对指针变量 p 加 1 , p 的值就会增加一个基本类型的长度。如果 p 指向整型数 ,且 p 的值为 1000,那么 ++p 的结果就是 1004。

2.2 用指针访问数组


数组名本身保存了数组的起始地址,即第 0 个元素的地址。不过数组名为指针常量,其值不能改变,仍然可以进行指针运算。

若定义了整型指针 p 和整型数组 arr,类型一致,因此可以执行 p=arr。
这个时候 p 就可以当做数组 arr 来使用。如 p[0] 。

所以可以通过以下4种方式输出数组的第 i 个元素。

cout<<arr[i];
cout<<*(arr+i);
cout<<p[i];
cout<<*(p+i);

但数组和指针还是存在本质上的区别。

3、动态内存分配


3.1动态变量的创建和消亡

创建用new,消亡用delete.

  • 创建

int *p;
p = new int;    //new int表示产生一个 int 型的变量,返回其地址给指针变量 p  ,变量类型必须与指针类型一致
*p =20;    //把产生的变量赋值20

或者

int *p=new int(20);     //与上面等效

或者

int *p=new int;
*p=20;      //与上面等效

也可以创建一个一位数组

int *p=new int[10];
//或者
int *p;
p=new int[10];

由于中括号内可以是变量,所以可以定义这样一个动态数组:

int n;
cin>>n;
int *p=new int[n];
  • 消亡
//格式
delete 指针变量;
//动态变量:
int *p=new int(10);
delete p;
//动态数组
int *p=new int[10];
delete []p;

这样就可以释放掉占用内存了。

3.2、内存泄漏


如果没有使用 delete 便不使用动态变量或动态数组,或者让指针指向另外一个变量,那原来的占用空间就会丢失,但堆管理器会认为我们一直在使用它们,这样一来,对于长时间使用的程序可能会耗尽所有内存,直至崩溃

3.3、查找new的失误


如果空间用完了,则int *p=new int;就会操作失败,返回空指针给 p ,也就是 p=0 。

3.4、拓展


3.4.1、auto与动态分配

auto p1=new auto(10);

自动判断类型

3.4.2、动态数组初始化

C++11中可以:

int *p=new int[5]{1,2,3,4,5};

如果给出初值个数少于数组元素个数,其余的自动赋值为0,多于则new操作失败。

3.4.3、一些细节

  • 动态变量或数组,若在全局中定义不再自动赋初值为0.
  • 作为局部变量的指针变量消亡了,不代表其所指的内存会释放.所以离开局部变量的范围后动态内存还在。
  • 动态内存用 delete 释放后,不代表指针会消亡.

4、字符串再讨论

用指针表示字符串有三种方法

将一个字符串常量赋给一个指向字符的指针变量,如

char *string="德克萨斯做的到吗!??"

将一个字符数组名赋给一个指针,字符数组中存储的是一个字符串。

申请一个动态的字符数组赋给一个指向字符的指针。


其中,①是把储存字符串"abcde"的内存的首地址复制给指针变量string,可以使用 string[i] ,但由于是指向常量的指针,所以不能改变该字符串中任何字符,也不能将该指针作为 strcpy 的参数。

5、指针与函数


5.1、指针作为形参


5.1.1、变量的地址作为函数参数

函数定义或申明可以

void swap(int *a,int *b);

调用可以

swap(&x,&y);

总之就是以传变量地址的方式来对实际参数造成影响。

5.1.2、数组作为函数参数再讨论

通过上面我们就可以更好地认识到——传递数组其实就是把数组的首地址传给形参中定义的数组,也就是指针常量传递给指针常量。

既然如此,假如定义个数组arr,我们也可以传递arr+i;(i是一个整数),如:

void quicksort(int arr[]){};
int main()
{
    int arr[10]={1,2,3,4,5,10,6,7,8};
    quicksort(arr+4);
}

就相当于把该数组的从下标'4'开始的子数组传递给另一个数组。

当然,我们也可以传递用指针来实现数组组的传递,如:

void quicksort(int *q){};
int main()
{
    int arr[10]={1,2,3,4,5,10,6,7,8};
    int *q=arr;
    quicksort(q+4);
}

但代码是给人看的,我们在设计代码时要让人能看出来这里是干嘛的,功能是什么,要能明确各个参数的用途,为了区分,求其对于初学者来说,传数组就用数组,传指针就用指针。

还有一点值得一提,作为形参定义的数组,它其实应该不能被称作数组,因为它的数组名就是一个指针变量,所以,作为形参定义的数组,其就是定义了一个指针变量,举例如下:

void damedane(int arr[]){};
void damedane(int arr[100]){};
void damedane(char *arr){};

以上三者等价。

参考自: dameyo~

5.1.3、字符串作为函数的参数

其实也就是传递数组,不过重要的是,在使用 cstring 里包含的函数时,我们可以包含指针运算,如:

strncmp(str1+1,str2+5,10);

这样子我们就可以把str1从下标1开始的长度为10的子串和str2小标从5开始的长度为10的子串进行比较了。之前因为求解类似的问题吃了绕了很多弯路,,,现在才知道原来可以这样,,,

对于其他函数也是同理。

5.2、返回指针的函数


返回指针的函数原型为:

<数据类型> *<函数名>(形参);

如函数返回值是一个指向字符的指针,该函数原型为:

char *subString(char *,int,int);

值得注意的是,当函数的返回值是指针是,返回地址的变量可以是全局变量或动态变量……但绝对不能是被调用函数的局部变量,这是因为当被调用函数返回后,局部变量已消失,当使用者通过函数返回的地址去访问地址中的内容时,会发现无权使用该地址。

当然,,,如果你函数里面用的是静态局部变量的话,就当我没说。

5.3、补充~


前面我们知道,可以用 const 来限制 *p 或 p ,在形参里,我们同样可以通过以下方式设计函数原型来限定形式参数:

int naya(const char *); 
int naya(char *const);
int naya(const char *const *);

分别可以对应

int naya(const char *str); 
int naya(char *const str);
int naya(const char *const *str);

效果可以联系上面内容脑补。

最后

可还行,明天继续,在指针结束的时候对以前的东西做个分类好了,指针这一章节细节和引入的概念有点多,不过还是蛮开心的哈哈哈,不过马上就要期中考了,能不能完成呢~?总之期待着吧!

标签:21,int,指针,地址,数组,new,20.11,变量
来源: https://www.cnblogs.com/Flowyuan-Foreverworld/p/14017759.html

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有