C++---基础篇(指针)

来源:互联网 发布:淘宝集分宝 编辑:程序博客网 时间:2024/05/01 14:07

二、指针变量的声明和使用

指针变量的类型

指针变量和指针是两个概念,为了方便记忆,读者可以把指针理解为地址,指针变量则是存储地址值的变量。

指针变量的声明

int  *pn,*pi;    //pn和pi是两个指向int型变量的指针;

float *pl;      //pl是一个指向float 型变量的指针;

char *pc;   //pc是一个指向char型变量的指针

int  *(pf)();   //pf是一个指向函数的指针,该函数返回值为int型数值;

int **pp;         //pp是一个指向指针的指针,即二维指针;

notice:在声明指针变量后,系统便给指针变量分配一个内存单元,各种不同类型的指针变量所占用的内存空间的大小是相同的,因为不同类型的指针变量存放的数据值都是内存地址值,是unsigned long 型的。

获得地址并对指针变量进行初始化

int *pa=&a;  //将a的地址赋给存放地址的变量(指针)

int *pb=&b[3];  //将b[3]的地址赋给存放地址的变量(指针)

----pa中保存的是变量a的地址值,也可以说pa指向了变量a。因为指针变量只能保存地址,所以不要将任何其他非地址值赋给一个指针变量,例如这样的赋值时不合法的:int *p=100;

特殊的值NULL

int *p=NULL(C++区分大小写),即指针没有指向任何地址,相当于房间建立好了,还没有装修,还不能住人。

指针变量的使用

#include <iostream>
#include<math.h>
#include<string.h>

using namespace std;

int main(){
    int n=10;
    int *pn=&n;                         //初始化指针变量pn,其值为变量n的地址,*pn现在代表变量n,对于*pn的任何操作都相当于对变量n的操作
    cout<<"n="<<n<<endl;
    cout<<"pn指向的值为:"<<*pn<<endl;
    n+=25;
    cout<<"n="<<n<<endl;
    cout<<"pn指向的值为:"<<*pn<<endl;
    *pn=*pn*10;
    cout<<"n="<<n<<endl;
    cout<<"pn指向的值为:"<<*pn<<endl;
    return 0;
}

指向指针变量的指针

int i=0;                //定义一个变量i

int *p=&i;                //定义一个指针变量p,并赋初值为i的地址;

int **pp=&p;              //定义一个指向指针变量的指针pp,赋初始值为p的地址。

三、指针变量的操作

指针变量的加减运算

#include <iostream>

using namespace std;

int main()
{
   int array[5]={1,2,3,4,5},n=1;
   int *p=&array[0];                                    //把数据元素array[0]的地址赋值给p
   for(int i=0;i<5;i++)
   {
       cout<<"p中的地址为:"<<p<<"\t其数值为:"<<*p<<endl;     
       p=p+n;                              //指针p的值加一       指针同整数n相加减,其实是把指针向前或向后移动n个对应类型的存储单元。

                                                              公式为:新地址=旧地址+n*指针指向的变量所占用的内存字节数       32位机,int占用4个字节
   } 
    return 0;
}

指针变量的关系运算

四、数组,字符串和指针

数组和指针

#include <iostream>

using namespace std;

int main()
{
   int array[5]={1,3,5,7,9};
   int *p=array;
   for(int i=0;i<5;i++){
        *(p+i)=i*2;                 //  把指针指向的数组元素的值改变
        cout<<array[i]<<" ";
   }
   cout<<endl;
    return 0;
}

 

一维数组中元素的指针表示法

int array[5]

用下标的方法来表示为:array[i]       //i=0,1,2,3,4

用指针的方法来表示为 *(array+i)           //i=0,1,2,3,4

二维数组的指针表示法

int array[3][3]         

用下标的方法表示为:array[i][j]           //i=0,1,2;j=0,1,2

用指针的方法表示为:*(*(array+i)+j)       //i=0,1,2;j=0,1,2

指针数组的声明为:数据类型 *数组名[数组大小]

字符串和指针

char str[]="this is C++ program";

char *pStr;

char *pStr="this is C++ program";

程序中:

char *pStr=NULL;

pStr="this is C++ program";  给字符指针赋值,将在内存中自动开辟的字符串数组的首地址赋值给字符指针变量pStr。

cout<<"pStr="<<pStr<<endl;输出字符串指针指向数据时,可以不用加*,因为其会自动从字符串指针指向的首地址开始输出

字符指针如果指向字符串常量,其内容是不能修改的,但如果指向字符数组是可以修改的。

 

五、常量指针和指针常量

常量指针格式:const 数据类型 *指针变量名

指针常量格式:数据类型 * const 指针变量名=&变量名

常量指针是保证通过指针间接访问的内存中的数据不被修改;指针常量是保证指针本身不会被修改。

六、指针和函数

指针作为参数:

例子:对于两个变量的值进行交换

#include <iostream>

using namespace std;
void swap(int *pa,int *pb);
int main()
{
    int a=88,b=208;
    cout<<"a="<<a<<"\tb="<<b<<endl;
    swap(&a,&b);                                   //调用交换函数,传递参数的地址值            把a和b的地址值(取a的地址,b的地址传给函数)赋值给形参
    cout<<"a="<<a<<"\tb="<<b<<endl;
    return 0;
}
void swap(int *pa,int *pb){                                   //定义交换函数 (接收到的参数为两个指针,即两个变量的地址)
    int temp;
    temp=*pa;
    *pa=*pb;
    *pb=temp;

}

指针作为函数参数时,可以修改函数外的数据,和引用差不多,为了避免指针作为函数参数导致函数外数据被意外修改,就需要使用const来保护指针指向的数据不被意外修改。例如:

#include <iostream>
void myCopy(int *pDst,const int *pSrc,int slen);
void disp(const int *p,int len);
using namespace std;

int main()
{
    int array1[20];
    int array2[10]={1,3,5,7,9,0,2,4,6,8};
    myCopy(array1,array2,sizeof(array2));
    disp(array1,10);
    return 0;
}
void myCopy(int *pDst,const int *pSrc,int slen)                                       //这个函数。。是乃个。。类似于字符串。。的strcpy函数。。。
{
    for(int i=0;i<slen;i++)
    {
        *pDst++=*pSrc++;
    }

}
void disp(const int *p,int len){
    for(int i=0;i<len;i++)
        cout<<*(p+i)<<" ";
        cout<<endl;
}

如果在函数myCopy中对源数组pSrc中的数据进行修改的话,代码就会产生编译错误,无法执行。这样就通过使用const来保护了指针指向的数据不被意外修改。

指针作为返回值:

指针函数:声明格式为:数据类型 *函数名(参数表)

如:int *func(int *a,int b);函数名为func,调用其后可以得到一个指向整数的指针。

例子:求数组中的最小数

 

#include <iostream>
int *min(int *array,int len);
using namespace std;

int main()
{
    int array[]={333,22,400,11,38};
    int *pMin=NULL;                                                       //初始化指针变量pMin;
    pMin=min(array,5);                                                     //调用min得到最小值的地址值;
    cout<<"min="<<*pMin<<endl;
    return 0;
}
int *min(int *array,int len){
    static int *p=array;                                                      //定义静态指针变量p,并初始化为数组array首地址
    for(int i=1;i<len;i++){
        if(*p>*(array+i)){                                               //比较是否当前元素值大于数组中其他元素值
            p=array+i;                                                      //如果大于,而把较小的一个元素的地址
        }
    }
    return p;                                                              //返回指针给主调函数,把静态指针指向的地址值返回
}                                                                                   

关于静态指针变量:是为了保证函数返回后,函数中的变量的值还存在,在函数内除了静态变量外,其他存储类型的变量都不能保证函数调用结束后仍然是有效的。

七、C++中灵活的空间---堆内存

堆内存也成为动态内存,C++在程序运行时,根据需求申请一定的内存空间来使用,这种内存环境随着程序运行的进展而时大时小,这种内存就是堆内存。

如何获得和使用堆内存

申请时格式为:

new    数据类型[表达式] ;                                                                                   

new是关键字,表明这是一个申请堆内存的操作。申请连续空间时,表达式的值是一个确定的正整数,可以是常量,也可以是变量。类似于声明数组时,给定的元素个数。方括号[ ]是不可省略的。如果只申请一个变量大小的空间,而表达式和方括号[]都可以省略,格式为:

new  数据类型 ;                                                                                                        

例子:

#include <iostream>

using namespace std;

int main()
{
    int *p=NULL;                                      //声明一个指针
    int size=0;                                              //声明一个整型变量,用来接收申请堆空间大小
    int i=0;
    cout<<"请输入需要生成的长度:";
    cin>>size;                                                   //接收对空间大小变量
    p=new int[size];                                               //申请堆内存空间,并把返回值赋值给p
    if(p==NULL){
        cout<<"申请空间失败"<<endl;                            //申请失败,退出程序
        return -1;
    }
    for(i=0;i<size;i++)
    {
    *(p+i)=i;                                                                 //把堆内存中申请的空间每一个进行初始化;
    }
    for(i=0;i<size;i++){
        cout<<*(p+i)<<" ";                                      //输出堆内存中申请的空间的数据值;
    }
    cout<<endl;
return 0;
}

 

如何释放堆内存

只申请空间不释放空间的情况称为内存泄露,所以申请内存空间后,应使用delete操作符来释放内存空间,格式为:

delete [ ]指针;

其中delete是关键字,表明是一个释放堆内存的操作,方括号“ [ ] ”表示释放的是堆内存中的连续内存空间。如果申请的只是一个堆内存变量,则会造成内存泄露的情况发生。

现在通过一个求n个数的和的例子,来理解堆内存的申请和释放。

#include <iostream>

using namespace std;

int main()
{
    int *p=NULL;
    int size=0,i=0,sum=0;
    cout<<"请输入需要计算的数字个数n:";
    cin>>size;
    p=new int[size];                                          //申请堆内存                申请之后一定要释放。
    if(p==NULL){
        cout<<"申请空间失败"<<endl;
        return -1;
    }
    cout<<"请连续输入n个整数:"<<endl;
    for(i=0;i<size;i++){
        cin>>*(p+i);
        sum+=*(p+i);
    }
    cout<<"sum="<<sum<<endl;
    delete p;                                                 //释放堆内存
return 0;
}

 

 

原创粉丝点击