指针使用灵活,但也最易犯错,当指针指定到错误的地址往往很不容易调试.
因此掌握指针的正确使用是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: "<<&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->y <<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.要求分配内存自行使用(或内存管理)
//***************
//指针下标超出数组范围