DotNet编程-星光伴我行

滴滴真谛 水滴石穿

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  指针使用灵活,但也最易犯错,当指针指定到错误的地址往往很不容易调试.
因此掌握指针的正确使用是C
++编程的一门基本功.

   本文有关的指针操作:
   
//*1**********使用指针与地址运算符*************
    
//*p表示p地址内指示的内容,p表示存储地址. 
    
//赋值时*p赋予所指变量的内容信息*p=a; 
    
//p用来赋予所指变量的地址信息p=&a.
    
//输出时p用来输出所指变量的内容信息,&p用来输出p的地址信息.
    
    
//指针类型在使用时,不可指向不存在的(void)位置,否则会造成不可预料的结果,
    
//基本上指针遵循下述两种情况:
    
//1.指向已存在的措针
    
//2.要求分配内存自行使用(或内存管理)
    UsePoints();
    
//*2**********指针地址运算*********************
    
//char *ch ; ch++;ch--;char类型在内存中占一个字节空间,地址增减量为1. 
    
//int *ptr; 4
    
//float *f; 4
    
//double *d; 8
    
//*p++;p++;*--p;*++p;(*p)++;(*p)--;
    CalAddressOfPointer();
    
//*3**********指针的内存配置********************
    
//配置单一内存
    
//配置单一内存并赋值
    
//配置多个内存,此种方式以指针当数组使用,又有固定大小或弹性大小.
     PointerMemSet();
     
//*4*********指针变量与二维数组*****************
     ArrayAndPointer();
     
//*5*********指针与函数*************************
     
//一般变量传递参数给指针,再返回来.
     VariMemberAndPointer();
     
//传址方式传参数
     
//使用地址运算符"&"也可实现,将数据从函数的参数部分返回参数.
     VariAddAndFunction();
     
//前两种方法的混合使用
     VariAndPointer();
     
//指针传给指针
     
//大家都是指针,避免传递参数时使用地址运算符"&"不留神时造成的错误.
     PointerAndPointer();
     
//函数名称以指针返回
     PointerFunction();
     
//*6******指针与结构******************************
     PointerAndStruct();
     
//*7******指针的指针(双指针)**********************
     DoublePointer();
     
//*8******以双重指针来赋值二维数组****************
     DoublePointerAndArray();
     
//*9******指针指向函数****************************
     PointerToFunction();
     
//*10*****指针数组********************************
     PointerArray();
     
//*11*****字符数组与字符串的常数设置**************
     CharArrayAndString();
     
//*12*****类的指针传递****************************
     UseDataHelperArray();

     详细代码:

//***********使用指针与地址运算符*************
//*p表示p地址内指示的内容,p表示存储地址. 
//赋值时*p赋予所指变量的内容信息*p=a; 
//p用来赋予所指变量的地址信息p=&a.
//输出时p用来输出所指变量的内容信息,&p用来输出p的地址信息.
//指针类型在使用时,不可指向不存在的(void)位置,否则会造成不可预料的结果,
//基本上指针遵循下述两种情况:
//1.指向已存在的措针
//2.要求分配内存自行使用(或内存管理)
void UsePoints()
{
    
int x=10;
    
int *p4;
    cout
<<"**********************************"<<endl;
    
//p4=x; //错误.将数值10赋给存储地址的指针是不对的.
    
//*p4=x; //错误,p4还没有指向内存的地址,不能给它赋值.
    p4=&x;   //p4指向x的地址
    cout<<"x中的值   :"<<x<<endl;   //10  
    cout<<"x的地址   :"<<&x<<endl;  //0x0012FF28
    cout<<"p4中的内容:"<<p4<<endl;  
    
//p4中保存了x在内存中的地址.即&x与p4值相同.p4保存了x的地址.
    cout<<"p4的地址  :" <<&p4<<endl; //p4的地址.与x的地址不同.
    cout<<"取出p4所指地址中的内容:"<<*p4<<endl; 
    cout
<<"**********************************"<<endl;
    
//指针赋值.
    
//指针类型之间可以互相赋值,即可以使许多指针指向同一个地址.
    int *p1;
    p1
=p4;
    cout
<<"p1=p4操作"<<endl;
    cout
<<"p1中的内容:"<<p1<<endl;  
    
//p1中保存了x在内存中的地址.即&x与p1值相同.p1保存了x的地址.
    cout<<"p1的地址  :" <<&p1<<endl; //p1的地址.与x,p4的地址不同.
    cout<<"取出p1所指地址中的内容:"<<*p1<<endl; 
    
    cout
<<"P4要求分配4个字节的内存空间自行使用"<<endl;
    p4
=new int//P4要求分配4个字节的内存空间自行使用.
    *p4=x; 
    cout
<<"p4:"<<*p4<< " &x: "<<&<<" &p4: "<<&p4<<endl;  
    
//值:10,0x0012FF28,0x0012FF24
    cout<<"**********************************"<<endl;
}

//***********指针地址运算*********************
    
//char *ch ; ch++;ch--;char类型在内存中占一个字节空间,地址增减量为1. 
    
//int *ptr; 4
    
//float *f; 4
    
//double *d; 8
    
//*p++;p++;*--p;*++p;(*p)++;(*p)--;
void CalAddressOfPointer()
{
    cout
<<"**********************************"<<endl;
    
int *p,a=10;
    p
=&a;
    (
*p)++//表示先输出*p的内容后,再而p++.其主要原因是*运算符拥有最高优先级;
    cout<<"*p,a: "<< *p<<""<<a<<endl; //11,11 均增1.
    *p++;   //表示先输出*p中内容11后,再p中的地址加1.
    cout<<"*p++:"<<*p<<endl;//1244968(p+1地址中的数,因机而异.)
    *p--;   
    cout
<<"*p--:"<<*p<<endl;//11.
    *++p;
    cout
<<"*++p:"<<*p<<endl;//1244968(p+1地址中的数,因机而异.)
    *--p;
    cout
<<"*--p:"<<*p<<endl;//11
    cout<<"**********************************"<<endl;
    
//数组访问, p1++的使用.
    int b[6]={1,2,3,4,5,6};
    
int *p1=b;
    
for(int i=0;i<6;i++)
    
{
        cout
<<"各元素地址:"<<endl;
        cout
<<"b["<<i<<"]"<<&b[i]<<endl;
        cout
<<"*p1内容:"<<*p1<<endl;
        cout
<<"p1地址:"<<p1<<endl;
        cout
<<"++(*p1):"<<++(*p1)<<endl; 
        
//先*p取出数据,然后对取出的数据加1.
        cout<<"(*p1)++:"<<(*p1)++<<endl;
        cout
<<"p1地址:"<<p1<<endl;
        p1
++;  //通过指针中的地址递增访问数组b中的数据.
    }

    cout
<<endl;
    
//p1=b; 
    
//
    p1=&b[0];
    
for(int w=0;w<6;w++)
        cout
<<p1++<<"  "<<*p1<<endl;
    cout
<<"**********************************"<<endl;
    
//字符数组的访问,*p3++的使用.
    char s2[10]="Morning";
    
char *p3=s2;
    cout
<<"一次输出一个字符"<<endl;
    
int ilen=strlen(s2);
    
//for(int j=0;j<ilen;j++)
    
//
    while(*p3)
        cout
<<*p3++<<","//M,o,r,n,i,n,g,
    cout<<endl;
    cout
<<"**********************************"<<endl;
    p3
=s2;
    
for(int j=0;j<ilen;j++)
        cout
<<p3++<<endl;   //输出p3所指的内容,非地址值;
    
//Monrning,onrning,g;
    cout<<"**********************************"<<endl;
    
char s[10]="Howareyou";
    
char *p2=s; //*p2中存储s的内容.
    
//指针p2变量占用4个字节的存储空间,用来存储s的地址信息;
    cout<<"p2指原内容:"<<p2<< " &p2地址:"<<&p2<<" &s地址:"<<&s<<endl; 
    
//Howareyou,OX0012FEF4,OX0012FEF8
    p2++;  //p2中存储的s地址信息加1.
    cout<<"p2++后内容:"<<p2<<" &p2地址:"<<&p2<<" &s地址:"<<&s<<endl; 
    
//owareyou,OX0012FEF4,OX0012FEF8
    cout<<"**********************************"<<endl;
    
char *str;
    
if((str=(char*)malloc(21))==NULL)
    
{
        cout
<<"内存不足"<<endl;
        exit(
1);
    }

    strcpy(str,
"goodMorning");  //将goodMorning复制给str.
    strcpy(s,str);
    cout
<<"所复制的数据为:"<<str<< endl;
    cout
<<"长度:"<<strlen(str)<<endl;
    cout
<<"**********************************"<<endl;
    
//p2=str;
    
//指针p2变量占用4个字节的存储空间,用来存储s的地址信息;
    cout<<"p2指原内容:"<<p2<< " &p2地址:"<<&p2<<" &s地址:"<<&s<<"s现在的值: "<<s<<endl; 
    
//oodMorning,OX0012FEF4,OX0012FEF8,goodMoning
    p2++;  //p2中存储的s地址信息加1.
    cout<<"p2++后内容:"<<p2<<" &p2地址:"<<&p2<<" &s地址:"<<&s<<"s现在的值: "<<s<<endl; 
    
//odMorning,OX0012FEF4,OX0012FEF8,goodMoning    
    free(str);
    cout
<<"**********************************"<<endl;

}

    
//***********指针的内存配置********************
    
//配置单一内存
    
//配置单一内存并赋值
    
//配置多个内存,此种方式以指针当数组使用,又有固定大小或弹性大小.
void PointerMemSet()
{
cout
<<"**********************************"<<endl;
//配置单一内存    
 int *a,b;
 a
=new int;
 cout
<<"a的地址:"<<a<<endl;
 cout
<<"b的地址:"<<&b<<endl;
 
*a=2;
 
*a+=6;
 cout
<<setw(6)<<"*a+6="<<setw(6)<<*a<<endl;
 delete a;
cout
<<"**********************************"<<endl;

//配置多个内存
int n;
n
=16;
int *b3;
b3
=new int[n];
int i=0;
for(i=0;i<n;i++)
{
    
*(b3+i)=rand()%16;
    cout
<<*(b3+i)<<",";
}

delete [] b3;
cout
<<endl;
cout
<<"**********************************"<<endl;
//c语言中的malloc与free写法,#include<stdlib.h> 或#include<alloc.h>
//要注意内存大小的匹配 char: 1; int: 4;float: 4;
int *a2;
if((a2=(int *)malloc(6*sizeof(int)))==NULL)
{
    cout
<<"内存不足"<<endl;
    exit(
1);
}
 //
//a2=(int *)malloc(17);//错误,配置17个字节的内存,非int类型所占内存的倍数.
for(i=0;i<6;i++)
{
    
*(a2+i)=rand()%16;
    cout
<<*(a2+i)<<",";
}

cout
<<endl;
free(a2);
cout
<<"**********************************"<<endl;

}


//**********指针变量与二维数组*****************
void ArrayAndPointer()
{
    cout
<<"**********************************"<<endl;
    
//指针变量与二维数组
    const int w=3,y=4;  //注意要定义为const,以便后面的int a[i][j]使用;
    int a[w][y],*p;
    
int i=w,j=y;
    p
=&a[0][0];  //p中只保存有a[0][0]的地址,p+m是地址值增加.
    int m=0;
    cout
<<"&p="<<&p<<endl;
    
for(m=0;m<w*y;m++)
    
{
        
*(p+m)=rand()%12;
        cout
<<*(p+m)<<" ";
    }


    cout
<<endl<<"数组内容为"<<endl;
    
    
    
for(m=0;m<3;m++)
            
for(int n=0;n<4;n++)
            
{
                cout.width(
3); //设置输出的字符宽度
                cout<<*(*(a+m)+n)<<"  ";
            }

    cout
<<endl<<"&p="<<&p<<endl;

    
//delete p;
    cout<<"**********************************"<<endl;
}

//*5*********指针与函数*************************
//函数与指针的可能组合
声明         调用            函数定义               说明
int a;       fc1(&a,);    void fc1(int *a,)   指针参数返回
int a;       fc1(a,);     void fc1(int &a,)   指针参数返回
int *a;      fc1(a,);     void fc1(int *a,)   指针参数返回
int *a;      a=fc1();     int  *fc1()         函数名返回
int *a,*b;   a=fc1(b,);   int  *fc1(int *b,)  函数名返回,指针参数返回
//一般变量传递参数给指针,再返回来.
int  Cal_data(int *a,int *b)
{
    
int t;
    t
=*a+100;
    
*a=*b;
    
*b=t+200;
    
return *b;
}

int VariMemberAndPointer()
{
    
int a,b;
    a
=10;
    b
=16;
    cout
<<"运算前:  a="<<a<<" b= "<<b<<endl;
    cout
<<Cal_data(&a,&b)<<endl ; //将两个变量的地址传给参数.
    cout<<"运算后:  a="<<a<<" b= "<<b<<endl; //a=16,b=310;
    return 1;
}


//***********************************
//传址方式传参数
//使用地址运算符"&"也可实现,将数据从函数的参数部分返回参数.
//通过指针与引用进行数据传递,可使程序在调用函数上更为灵活,但必须注意
//传递参数的相互关系
/////////////////////////////////////////////////
主程序调用                   函数定义
int a,*b;
fc1(
&a);        ->           void fc1(int *a)
fc1(a);         
->           VOID fc1(int &a)  
fc1(b);         
->           VOID fc1(int *b)  
/////////////////////////////////////////////////
int  Cal_data(int &,int &);//先声明

 
int VariAddAndFunction()
 
{
     
int a,b;
     a
=10;
     b
=16;
     cout
<<"运算前:  a="<<a<<" b= "<<b<<endl;
     cout
<<Cal_data(a,b)<<endl ; //将两个变量的地址传给参数.
     cout<<"运算后:  a="<<a<<" b= "<<b<<endl; //a=16,b=310;
     return 1;
 }

 
int  Cal_data(int &a,int &b)
 
{
     
int t;
     t
=a+100;  //不能使用t=*a+100; *a为指针类型.
     a=b;
     b
=t+200;
     
return b;
 }

//*********************************************
//前两种方法的混合使用
int  Cal_data(int &a,int *b);
  VariAndPointer()
  
{
      
int a,b;
      a
=10;
      b
=16;
      cout
<<"运算前:  a="<<a<<" b= "<<b<<endl;
      cout
<<Cal_data(a,&b)<<endl ; //将两个变量的地址传给参数.
      cout<<"运算后:  a="<<a<<" b= "<<b<<endl; //a=16,b=310;
      return 1;  
  }

  
int  Cal_data(int &a,int *b)
  
{
      
int t;
      t
=a+100;  //不能使用t=*a+100; *a为指针类型.
      a=*b;
      
*b=t+200;
      
return *b;
  }

  
//指针传给指针
  
//大家都是指针,避免传递参数时使用地址运算符"&"不留神时造成的错误.
  int Get_Data(int *a,int *b)
  
{
     
      
*a=10;
      
*b=20;
      
return *b;
  }

int PointerAndPointer()
{
    
int *a,*b;

    a
=new int;
    b
=new int;
    cout
<<Get_Data(a,b);
    cout
<<"取出a,b的值"<<*a<<"  "<<*b<<endl;
    delete a;
    delete b;
    
return 1;
}

//函数名称以指针返回
int *Get_data1(int ,int);
int *Get_Array();
char *Get_String();
int PointerFunction()
{
    
int a=10,b=20,*p;
    p
=Get_data1(a,b); 
    cout
<<"p="<<*p<<endl;
    delete p;

    
int *p2=new int[11];
        cout
<<"&p2="<<&p2<<endl;
    p2
=Get_Array();
    cout
<<"p2=";
    
for(int i=0;i<9;i++)
    cout
<<*p2++<<",";
    cout
<<"&p2="<<&p2<<endl;

    cout
<<endl;
    
int j=0;
    
for ( j=0;j<9;j++)
        
//*p2--;
    cout<<"&p2="<<*p2--<<endl;  //一定要加上此句.
    delete [] p2;
    
char *p3=new char[13];
    cout
<<"&p3="<<&p3<<endl;
    p3
=Get_String();
    cout
<<"p3="<<p3<<endl;
    cout
<<"&p3="<<&p3<<endl;
    
int x=sizeof(p3);
    cout
<<"p3长度"<<x<<endl;
    
for (j=0;j<13;j++)
    cout
<<"&p3="<<p3--<<endl;
    
//delete [] p3;
    return 1;
}

int *Get_data1(int a,int b)
{
    
int *p=new int(a+b);
    
return p;
}

int *Get_Array()
{
    
int *p=new int[11];
    
for(int i=0;i<9;i++)
        
*(p+i)=i*2;
    
return p;
}

char *Get_String()
{
    
char *p=new char[13];
    p
="good morning";
    
return p;
}

//指针与结构
typedef struct student
{
char name[4];
char sex;
int age;
}
_student;
void get_student(student *a)
{

    
    a
->name[0='b';
    a
->name[1='l';
    a
->name[2='g';
    a
->name[3='c';

    a
->sex ='f';
    a
->age =23;
}

int PointerAndStruct()
{
   student blgc;
get_student(
&blgc);
cout
<<"name="<<blgc.name <<endl;
cout
<<"sex="<<blgc.sex  <<endl;
cout
<<"age="<<blgc.age  <<endl;

return 1;
}

//指针的指针(双指针)
int DoublePointer()
{
    
//*p  地址->内容
    
//**p 地址->地址->内容
    int x,*p,**p2;
    x
=100;
    p
=&x;
    p2
=&p;
    cout
<<"*p="<<*p<<endl;  //100
    cout<<"&p="<<&p<<endl;  //0x0012FF24
    cout<<"*p2="<<*p2<<endl; //0x0012FF28
    cout<<"**p2="<<**p2<<endl; //100
    return 1;
}

//以双重指针来赋值二维数组
//先要求行的指针,再以行的指针来赋值列的指针,使行为第一指针,
//列为第二指针,形成数组的数组,其访问方式可用一般数组的访问方式.
const int row=2;
const int col=3;
int Get_Array(float **data)
{
    srand((unsigned)time(NULL));
//启动随机函数生成器
    randomize();
    
int temp=0;
    
for(int i=0;i<row;i++)
        
for(int j=0;j<col;j++)
        
{
            temp
=random(10); //产生0-9的随机数
            data[i][j]=(float)temp;
        }

           
return 1;
}

void Display(float **data)
{
for(int i=0;i<row;i++)
{
    
for(int j=0;j<col;j++)
            cout
<<data[i][j]<<" ";
cout
<<endl;
}


}

void Dispose(float **data)
{
    
for(int i=0;i<row;i++)
    
{
        delete [] data[i]; 
//释放列
    }

    delete [] data; 
//释放行
}

 
int DoublePointerAndArray()
{

float **data;
try
{
    data
=new float *[row];  //配置行
    for(int j=0;j<row;j++)
        data[j]
=new float[col]; //配置列
    throw(1); //自定义抛出一个异常数字1.
}

catch(int err)
{
    
if(err!=1)
    
{
        cout
<<"内存不足,"<<endl;
        exit(
-1);
    }

}

Get_Array(data);
Display(data);
Dispose(data); 
//释放内存
return 1;
}

//指针指向函数
//函数虽然不是变量,但它仍然在内存中有实际地址,故可以将指针指向该地址.
//要取得函数地址,只要将函数名称赋值给指针变量,而不用任何括号或参数,就
//象数组的地址赋值给指针变量一样.
double xpowxy(double,double,double(*xy)(double,double));
double add(double x ,double y);
int PointerToFunction()
{
    
//指针指向pow函数,用以求x的y次方值.
    double x,y;
    
double (*p)(double,double);
    
//p=pow;
    p=add;
    x
=10;
    y
=2;
    
//cout<<"x^y="<<xpowxy(x,y,p)<<endl;
    cout<<"x+y="<<xpowxy(x,y,p)<<endl;
    
return 1;
}

double xpowxy(double x,double y,double(*xy)(double ,double))
{
    
return xy(x,y);
}


double add(double x ,double y)
{
    
return x+y;
}


//指针数组
int PointerArray()
{
    
int *p[6],i=0;
    
for(i=0;i<6;i++
    
{
        p[i]
=new int(i*2); //分配内存空间,赋初值.
    }

    
for(i=0;i<6;i++)
    
{
        cout
<<*p[i]<<endl;  //输出结果
    }

    
for(i=0;i<6;i++)
    
{
        delete p[i]; 
//释放资源
    }

    
return 1;
}

//字符数组与字符串的常数设置
const int N=6;
int CharArrayAndString()
{
    
int i;
    
char s[N]={'a','b','c','d','e'}//纯字符数组非字符串,没有结束符'\0'

    
char st[N+1]={'A','B','C','D','E','\0'};    //纯字符数组的字符串
    char str[]="ABCDE";
    
char *string="ABCDE";
    cout
<<"字符数组输出s[N]=";
    
for (i=0;i<N;i++)
        cout 
<< s[i];
    cout 
<< endl;
    cout 
<<"字符串输出st[N+1]="<<st<<endl;
    cout 
<<"字符串输出str[]="<<str<<endl;
    cout 
<<"字符串输出*string="<<string<<endl;
    
return 1;
}



class DataHelper
{
private :
    
int x;
    
int a[10];
    
public :
    
int *Group1[20];
    
static int Group2[20];
    
int Group3[20];
    
int y;
    
static int z;
    DataHelper();
    
int GetGroup1();
    
int SetGroup2(int b[20]);
}
;

int DataHelper::z ; //静态成员声明,切记.
int DataHelper::Group2[20]; 
DataHelper::DataHelper()
{
    x
=10;
    y
=-1;
    z
=-1;
    
for(int i=0;i<20;i++)
    
{
        Group1[i]
=new int(-1);
        Group2[i]
=-1;
    }

    memset(Group3,
-1,sizeof(Group3));
}

DataHelper::SetGroup2 (
int b[20])
{

    
for(int i=0;i<20;i++)
    
{
      Group2[i]
=b[i];
    }

    
return 1;
}

int UseDataHelperArray()
{
    DataHelper 
*dh;


    dh
=new DataHelper();
    
*(dh->Group1[0])=10;
    
*(dh->Group1[0])=20;
    dh
->y=20;
    DataHelper::z
=100;

    
int a[20];
    
    memset(a,
100,sizeof(a));
    dh
->SetGroup2(a) ;
    DataHelper::Group2[
0]=100;
    
    cout
<<"dh->y="<<dh-><<endl;
    cout
<<"dh->Group1[0]="<<*(dh->Group1[0])<<endl;
    cout
<<"dh->Group1[1]="<<dh->Group1[1]<<endl;
    cout
<<"DataHelper::z"<<DataHelper::z<<endl;
    cout
<<endl<<endl;
    
    cout
<<"dh2->Group2[0]="<<DataHelper::Group2[0]<<endl;

    DataHelper 
*dh2;
    dh2
=new DataHelper;
    cout
<<endl<<endl;
    
    cout
<<"dh2->Group1[1]="<<dh2->Group2[1]<<endl;
   
    
return 1;

}




#include 
<iostream.h>//cout,cin
#include <iomanip.h>//setw()
#include <conio.h> //getch()
# include <stdio.h>
# include 
<stdlib.h>
# include 
<string.h>
# include 
<time.h>
# include 
<math.h> //pow(x,y)
#define randomize() srand((unsigned) time(NULL))
#define random(x) rand()%x
//#include <alloc.h>
#include <process.h>
//#include <except.h>

//指针使用灵活,但也最易犯错,当指针指定到错误的地址往往很不容易调试.
//因此掌握指针的正确使用是C++编程的一门基本功.

//**************
//指针类型在使用时,不可指向不存在的(void)位置,否则会造成不可预料的结果,
//基本上指针遵循下述两种情况:
//1.指向已存在的措针
//2.要求分配内存自行使用(或内存管理)
//***************
//指针下标超出数组范围

posted on 2006-08-25 17:00  DotNet编程  阅读(1326)  评论(0编辑  收藏  举报