C++指针

1 指针的概念

#include <iostream>
using namespace std;
/*
间接引用指针时,可获得该指针指向的变量内容 
本部分参考内容:C++ 程序设计教程 钱能   清华大学出版社 
*/
void zhizhen1()
{
    int* iPtr;
    int iCount=18;
    //* 放在可执行语句中的指针之前,成为间接引用操作符
    iPtr=&iCount;
    //* 放在指针定义中时,称指针定义符 
    cout<<*iPtr<<endl;
    cout<< iPtr<<endl;
    *iPtr=58;
    cout<< iCount<<endl;
    cout<< iPtr<<endl;
}
void zhizhen2()
{
    /*
    *iPtr的类型是整数 ,指针iPtr指向该整数,所以iPtr的类型是整型指针,
    而iPtr的地址(&iPtr) 的类型是整型指针的地址,即指向整型指针的指针。
    指针的地址是二级指针     
    */     
    int iCount=18;
    int* iPtr=&iCount;
    *iPtr=58;
    cout<<iCount<<endl;//58
    cout<<iPtr<<endl;//iCount所在的地址
    cout<<&iCount<<endl;//iCount所在的地址
    cout<<*iPtr<<endl;//iCount的值
    //指针也是变量,是变量就具有的内存地址,所以指针 也有地址 
    cout<<&iPtr<<endl;// iPtr本身的地址    
} 
void zhizhen3()
{
    int iCount=26;
    int* iPtr=&iCount;
    //指针值不是整型数 
    //* iPtr=(int)&iCount;
    *iPtr=50;
}
void zhizhen4()
{
    //指针的初始化,指针变量的初始化的值为该指针类型的地址值
    //不要将 int* iPtr=&iCount与 * iPtr=&iCount混搅
    //前者是定义语句,*是指针定义符,C++为iPtr指针分配一个指针空间,并用iCount的地址初始化
    //后者是赋值语句,左右两边地址不匹配
    //指针要在使用前初始化 
    int iCount;
    int* iPtr=&iCount;//初始化未整型地址 
    *iPtr=58; 
    cout<<*iPtr<<endl;//iCount的值
    cout<<iCount<<endl;
}
void zhizhen5()
{
  //指针类型与实际存储的匹配
  //指针是有类型的    ,给指针赋值,不但必须是一个地址,而且应该是一个该指针类型相符的变量或变量地址
  //指针具有一定的类型,它的值为地址的变量,该地址是内存中另 一个该类型变量的存储位置,或者说指针是具有某个类型的地址 
  float f=34.5;
  float* fPtr=&f; 
  float* f1Ptr; 
  //int* iPtr=&f;//    [Error] cannot convert 'float*' to 'int*' in initialization  
  cout<<f<<endl;  
  //cout<<iPtr<<endl;
  cout<<fPtr<<endl;
  f1Ptr=fPtr;
   cout<<*f1Ptr<<endl;
} 
    
 

 

*p++ ,由于++和*的优先级相同,结合方向为自右至左。所以确实*p++等价于*(p++),而p++其实取值的时候还是取p的,是用过之后才能+1。所以*(p++)就是先执行p++得到p,然后执行*p,得到p指向的值,等这个运算结束了才能+1。

 2 指针运算

 

void zhizhen6()
{
    //指针运算
    //只有加法和减法可以进行指针运算 
    int aArray[10];
    int sum=0;
    int* iPtr=aArray;
    cout<<sizeof(*aArray)<<endl;
    
    char fArray[10];
    cout<<sizeof(*fArray)<<endl;
    for (int i=0;i<10;i++)
    {
        //a[i] 等价 *(a+i) 等价于 iPtr[i] 等价于*(iPtr+i)         
        //aArray[i]=i*2;
        //*(iPtr+i)=i*2;    
        //iPtr[i]=i*2;    
        *(aArray+i)=i*2;
        //指针和数组
        //数组名可以直接拿来初始化指针,数组名就是数组第一个元素的地址。 
        //即对于数组a,有:a 定于&a[0]
        // int a[100] ; int* iPtr=a;
        //a[i] 等价 *(a+i) 等价于 iPtr[i] 等价于*(iPtr+i)  下标操作是针对地址而不仅仅是针对数组名
        //&a[i]等价于a+i等价于iPtr+i等价于&iPtr[i]
    }
    for (int i=0;i<10;i++)
    {
        sum+=*iPtr; 
        cout<<"aArray  地址"<<iPtr<<endl;
        cout<<"sum is"<<sum<<endl;
        iPtr++;
        //sum+=*(iPtr++) ;
    }    
    cout<<"sum is"<<sum<<endl;
}    

 

3 指针与数组

void zhizhen7()
{
    int sum1=0,sum2=0,sum3=0,sum4=0,sum5=0;
    int iArray[]={1,4,2,7,13,32,21,48,16,30};
    int* iPtr;    
    int size,n;
    size=sizeof(iArray)/sizeof(*iArray);//元素个数
    for (n=0;n<size;n++) 
    {
        sum1+=iArray[n];
    }
    iPtr=iArray;
    for (n=0;n<size;n++)
    {
        //cout<<*iPtr<<"    "<<sum2<<endl;
        sum2+=*iPtr++;        
        //sum2=sum2+*iPtr;
        
        //iPtr++;
    }
    cout<<sum2<<endl;
    iPtr=iArray;
    for (n=0;n<size;n++)
    {
        sum3+=*(iPtr+n) ;
    }
    iPtr=iArray;
    for (n=0;n<size;n++)
    {
        sum4+=iPtr[n];
    }
    iPtr=iArray;
    for (n=0;n<size;n++)
    {
        sum5+=*(iArray+n);
    }
    
    cout<<sum1<<endl
        <<sum2<<endl
        <<sum3<<endl
        <<sum4<<endl
        <<sum5<<endl;        
    
}
 

 数组名是指针常量,区别于指针变量,所以给数组名赋值时错误的

对于编译器来说,数组名表示内存中分配了数组的固定位置,修改了这个数组名,就会丢失数组空间,所以数组名所代表的地址不能被修改。

4 堆内存分配

#include <iostream>
#include <malloc.h>

void zhizhen8()
{
    //堆内存分配
    //堆允许程序在运行时(而不是在编译时) ,申请某个大小的内存空间
    int arraysize;//数组大小 
    int *array;
    cout<<"please input a number of array elements:\n" ;
    cin>>arraysize;
    //堆内存分配 
    /*
    程序编译和连接时, 在栈中分配了arraysize整型变量和array整型指针变量空间。
    程序运行时,调用 函数malloc() ,malloc()函数在堆中寻找未被使用的内存,找到所需的字节数后返回该内存的起始地址。
    malloc()函数并不知道这些内存做什么,所以它返回一个没有类型的指针。
    但是对整数指针     array来说,malloc()函数的返回值必须显式转换成整数类型指针才能被接受。
    void *malloc(size_t size)
    */
    // array=(int*)malloc(arraysize*sizeof(int));
    if ((array=(int*)malloc(arraysize*sizeof(int)))==NULL)
    {
        cout<<"can't allocate more memory,terminating.\n"; 
        exit(1);
    }
    for (int count=0;count<arraysize;count++)
    {
        array[count]=count*2;
    }
    for (int count=0;count<arraysize;count++)
    {
        cout<<array[count]<<"    ";
    }
    cout<<endl;
    //释放堆内存 (void free(void *))
    free(array);
}

void zhizhen9()
{
    //new和delete
    /*
    new 和 delete 是C++专用操作符, 它们不用头文件声明。
    new 类似于函数malloc(),分配堆内存,但比malloc()更简练。
    new 的操作数为数据类型,它可以带初始化值表或单元个数,new返回一个具有操作数之数据类型的指针;
    delete 类似于函数free(),释放堆内存。delete 的操作数是new的返回的指针,  当返回的是new分配的数组时,应该带[]
    new 和 delete在性能上逊于函数malloc()和free(),但却更加安全具有丰富的功能。 
    */ 
    int arraysize;//数组大小 
    int *array;
    cout<<"please input a number of array elements:\n" ;
    cin>>arraysize;
    if (((array=new int[arraysize]))==NULL)
    {
        cout<<"can't allocate more memory,terminating.\n"; 
        // 用来立即中止当前程序的执行,并将一个整数返回给系统
        exit(1);
    }
    for (int count=0;count<arraysize;count++)
    {
        array[count]=count*2;
    }
    for (int count=0;count<arraysize;count++)
    {
        cout<<array[count]<<"    ";
    }
    cout<<endl;
    //释放堆内存
    delete[]array;    
}

5 const 指针

 

 

 

void zhizhen10()
{
    //count指针     
    //1 指向常量的指针 在指针定义语句的类型前加const,表示指向的对象是常量。
    /*
    const int a=78;
    const int b=28;
    int c=18;
    const int *pi=&a; //指针类型前加const
    *pi=58;//error:不能修改指针指向的常量
    pi=&b;//OK 指针值可以修改
    *pi=68;// error:不能修改指针指向的常量
    const int *pi=&a; //告诉编译,*pi 是常量,不能将*pi作为左值进行操作; 
    pi=&c;     
    */
     char a[20]="How are you!";
     char b[20];
     mystrcpy(b,a);
     cout<<b<<endl;         
    //2 指针常量 :在指针定义语句的指针名前加const,表示指针本身是常量
    //在定义指针常量时必须初始化,就像常量初始化一样。 
    /*
    char *const pc="asdf";
    pc="asdasdasd"; //error
    *pc='b' //OK pc的内容为 bsdf ;
    *(pc+1)=c //OK pc的内容为 bcdf
    *pc++='y' //error:指针常量不能修改其指针值 
    const int b=28;
    //指针常量定义  int *counst pi=&b ;告诉编译,pc是常量,不能作为左值进行操作,但是允许修改间接访问值,及*pc可以修改 
    int *counst pi=&b ;//error :不能将const int *转换成int * 
    */   
    //3 指向常量的指针常量 (常量指针常量) 
    //常量指针常量定义"const int* const cpc=&b;"  告诉编译,cpc 和*cpc都是常量,他们都不能作为左值进行操作
    /*
    const int ci=7;
    int ai;
    const int* const cpc=&ci; //指向常量的指针常量 
    const int* const cpi=&ai; //OK
    cpi=&ai;                  //error 指针值不能修改
    *cpi=39;                  //error 不能修改指向的对象
    ai=39;                    //OK
    */ 
    
         
} 

6 指针与函数

void zhizhen11_2()
{
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    int* p1=a;
    while (*p1!='\0')
    {
      cout<<*p1++<<endl;    
      //p1++;
    }    
} 
//void zhizhen11_1(int array[],int n)
void zhizhen11_1(int *array,int n)
{
    int sum=0;
    for (int i=0;i<n;i++)
    {
        sum+=*array;
        array++;    
    }
    cout<<sum<<endl;
} 
void zhizhen11_2(int* x,int* y)
{
    int temp=*x;
    *x=*y;
    *y=temp;
}
void zhizhen11()
{
    
    //1 指针与函数
    /*
    1 传递数组的指针性质
    一旦把数组作为参数传递到函数中,则在栈上定义了指针,可以对该指针进行递增,递减操作     
    */ 
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    zhizhen11_1(a,10);
    //2 使用指针修改函数参数 
    /*
    2 使用指针修改函数参数
    以a 和b 的地址传递给zhizhen11_1函数时,函数复制了这两个地址,并赋值给x 和y 这个两个指针,这两个指针是指向变量a 和b 的
    */
    int a1=2,b1=3;
    cout<<"a="<<a1<<" ,b="<<b1<<endl;
    zhizhen11_2(&a1,&b1);
    cout<<"a="<<a1<<" ,b="<<b1<<endl;
    //3 指针函数
    /*
    3 返回指针的函数成为指针函数
    指针函数不能把在它内部说明的具有局部作用域的数据地址作为返回值。 
    */ 
    //4 void指针
    /*
    4 空类型指针不能进行任何操作,也不能进行间接引用,因为指针运算和间接引用都需要指针类型信息 
    */
     
}

 

void zhizhen11_2()
{
    int a[11]={1,2,3,4,5,6,7,8,9,10,11};    
    int* p1=a;
    int n=sizeof(a)/sizeof(a[0]);
    while (*p1!='\0')
    {
      cout<<*p1<<endl;    
      p1++;
      //n++;
      //cout<<n<<endl;
    }        
    /*
    cout<<n<<endl;
    for (int i=0;i<n;i++)
    {
        cout<<*p1++<<endl;
    }    
    */

} 

 

void zhizhen11_4()
{
    /*
    函数声明:void * memcpy ( void * destination, const void * source, size_t num );
    参数
    目的地:指向要在其中复制内容的目标数组的指针,类型转换为 void* 类型的指针。
    源:指向要复制的数据源的指针,类型转换为 const void* 类型的指针。
    数字:要复制的字节数。 size_t 是无符号整数类型。
    头  文  件:#include <string.h>
    返  回  值: 返回目的地。
    */
    //void指针
    char src[10] ="*******";
    char dest[10];
    char* pc=(char*)memcpy(dest,src,10);
    cout<<pc<<endl;
}

 7 字符指针

void zhizhen12()
 {
     //字符指针
    /*
    1 字符数组和字符串常量
    字符串的类型是指向字符的指针(字符指针char*),它与字符数组同属于一种类型,以'\0' 结尾 
    */ 
    char buffer[]="hello!"; //字符数组     
    char *p1=buffer;
    cout<<buffer<<endl;
    while (*p1!='\0')
    {
      cout<<*p1++;          
    }        
    cout<<endl;
    cout<<"Hello World!"<<endl;//字符串常量 
    
 }
  void zhizhen12_1()
  {
      //字符指针 
      char buffer[]="hello!"; 
      char *p1;
      p1=buffer;
      cout<<p1<<endl;
      p1++;
      cout<<p1<<endl;
      cout<<*p1<<endl;            
  }
  #include <string.h>
  void zhizhen12_2()
  {
        //字符串比较:两个字符串比较的是地址的比较,,同理两个数组的比较也是地址的比较
      char buffer1[] ="hello";
      char buffer2[] ="hello";
      if (buffer1==buffer2) 
      {
          cout<<"equal"<<endl;
      }
      else
      {
          cout<<"not equal"<<endl;
      }
      /*
      strcmp函数strcmp函数是比较两个字符串的大小,返回比较的结果。一般形式是:
      i=strcmp(字符串,字符串);其中,字符串1、字符串2均可为字符串常量或变量;
      i 是用于存放比较结果的整型变量。
      比较结果是这样规定的:
      ①字符串1小于字符串2,strcmp函数返回一个负值;
      ②字符串1等于字符串2,strcmp函数返回零;
      ③字符串1大于字符串2,strcmp函数返回一个正值;
      */
      if (strcmp(buffer1,buffer2)==0)
      {
          cout<<"equal"<<endl;
      }
      else
      {
          cout<<"not equal"<<endl;
      }
  }

 字符串赋值

  void zhizhen12_3()
   {
          //字符串赋值
       char buffer1[10];
       strcpy(buffer1,"Hello");
       cout<<buffer1<<endl;       
       char buffer2[10];
       strcpy(buffer2,buffer1);
       cout<<buffer2<<endl;     
   }
 
 
 char* copy_string(const char* src, char dest[]) {
    if (src==NULL || dest==NULL) {
        return NULL;
    }
    int i=0;
    while(*src != '\0') {
        dest[i++] = *src++;
    }
    dest[i] = '\0';
    return dest;
}

 void copy_string_imp() {
    const char* src = "abcdefg";
    int i=0;
    while(src[i] != '\0') {
        i++;
    }
    char dest[i+1];
    copy_string(src, dest);
    cout<<dest<<endl;
}

 8 指针数组

 

 

void zhizhen13_1(char* arr[],int len)
{
    for (int i=0;i<len;i++)    
    {
        cout<<&arr[i]<<"    ";
        cout<<arr[i]<<endl;
    }
}
void zhizhen13()
{
     //指针数组 指针数组名是指向指针的指针(即二级指针) 
    char* pn[]={"Fred","Bareny","Wilma","Betty"};
    int num=sizeof(pn)/sizeof(char*);
    cout<<sizeof(pn)<<endl;
    cout<<sizeof(char*)<<endl;
    cout<<num<<endl;
    zhizhen13_1(pn,num);
}

void zhizhen13_3(char* arr[])
{

    while (*arr!=NULL)
    {
        cout<<arr<<"    ";
        cout<<*arr++<<endl;
    }
}
void zhizhen13_2()
{
    //NULL 指针:NULL 是空指针,它不指向任何地方 
    char* pn[]={"Fred","Bareny","Wilma","Betty",NULL};
    cout<<sizeof(pn)<<endl;
    cout<<sizeof(char*)<<endl;
    zhizhen13_3(pn);
}

 9 命令行参数

int main(int argc, char** argv) {
    //命令行参数 C++程序是操作系统调用的函数
    //argc表示参数的个数,argv表示参数数组 
    /*
    int iCount=0;
    while (iCount<argc)     
    {
        cout<<"argc"<<iCount<<":"<<argv[iCount]<<endl;
        iCount++;
    }
    */
    
    int i=0;
    while (*argv) 
    {
            cout<<"argc"<<i++<<":"<<*argv++<<endl;
    }
    return 0;
}

 

posted @ 2023-02-10 09:39  jhtchina  阅读(75)  评论(0)    收藏  举报