一、 指针的概念
1.指针含义: 指针就是内存地址。
2.定义:
l 指针是一个变量,其内容为内存地址。
l 指针定义与其他普通变量类似,凡是声明变量的地方,就可声明指针变量。
l 指针变量只是分配了分配了存放地址的空间,但未具体将某个确切地址存入其中。
类型 *指针名;
类型:int,float,char,double……
3.建立指针:
int *iptr,*iptr2;
int a=180; int b=120;
iptr1=&a; //iptr1的值就是a的地址。
iptr2=&b; iptr1=iptr2;
4. 间接引用指针操作符:*
b=*iptr1;
5. 指针变量的地址:
int m=150; int *ptr=&m;
cout<<m<<endl; cout<<ptr<<endl;
cout<<&m<<endl; cout<<*ptr<<endl;
cout<<&ptr<<endl;
6. 指针的初始化:
定义时初始化
运行时初始化
7.指针数组
l 指针的运算(+/-)是以指针的类型展开的。
l 数组名本身就是数组的起始地址。
l 数组名初始化指针:
int a[20];
int *ptr=a; 或 int *ptr=&a[20]; int *ptr=:a;
l 指针与数组的等价操作:
a[i]=*(a+i)=ptr[i]=*(ptr+i);
&a[i]=a+i=ptr+i=&ptr[i];
注意:sizeof(a)与sizeof(*a)的区别!
l 数组名是指针常量----不是左值
int a[200];
a++; //error!
二、 堆内存
1.堆内存是程序运行时临时申请的内存空间,是动态空间。
2.malloc()与free()函数
void *malloc(size);
void *free(void *);
int *ptr;
ptr=(int *)malloc(1000);
…
free(ptr);
1. new与delete操作符
l new分配单个变量-----可提供初始值
int *pi;
pi=new int; pi=new int(100);
l new分配数组-----不能提供初始值
new type[size];
int *pi; pi=new int[100];
l 分配多维数组:
指针p定义为: type (*p)[m][n]…[s];
p=new type[size][m][n]…[s];
其中,m,n…s为整常数,size为整形表达式,该语句建立了有size个元素,
每个元素类型为type[m][n]…[s]的数组,new 返回指向第一个元素的指针。
delete p;
new分配的地址不能改变,将用于delete的释放。
注意:申请内存后,一定要进行是否成功判断。一般申请不到时,返回空指针NULL。
用完内存后,一定要释放所申请的空间。
例:
#include <iostream.h>
//#include <malloc.h>
void main()
{
int arraysize;
int *array;
cout<<"input a number of array:/n";
cin>>arraysize;
array=new int[arraysize])
if((array==NULL)
{
cout<<"can't allocate more memory, return./n";
return;
}
for (int count=0;count<arraysize;count++)
{
array[count]=count*2;
cout<<array[count]<<" ";
}
cout<<endl;
delete[]array;
}
三、 const指针(了解)
1. 指向常量的指针
const int a=28; const int b=36;
const int *pi=&a;
pi=&b; //OK! *pi=56; //error!
pi b
7800:0100(pi地址):7800:0120->7800:0120(b地址):36
pi指向的对象值不能被修改,pi本身可以被修改。
2. 指针常量
指针前加上const
int *const pi;
pi本身不能被修改,pi指向的对象值可以被修改。
3. 指向常量的指针常量
const int a=5;
const int * const pi=&a; //pi和*pi都不能被修改!
四、 字符指针
1. 字符数组和字符串常量------常量指针
字符串常量存放于data区的const区中。
“china”≠ “china”, 两者是地址的比较,要用strcmp()比较!
2. 字符指针
字符串常量,字符数组名,字符指针均属于同一数据类型!
char *ptr=”hello”;
cout<<ptr<<endl; hello
cout<<ptr+1<<endl; ello
cout<<*ptr<<endl; h
3. 字符串比较
l 两个字符串常量的比较是地址的比较,两个数组名的比较也是地址的比较。
l 字符串内容的比较函数
int strcmp(char *str1,char *str2);
int =0: str1=str2;
>0: str1>str2;
<0: str1<str2;
4. 字符串赋值
l 不能对字符数组赋一个字符串
l char *strcpy(char *dest,char *src);
l 数值型数组的赋值函数
memcpy(int *ary1,int *ary2,int n_size);
五、 关于NULL指针和void指针
l NULL是一个指针值,任何指针都可以赋予该值。
l void 只表示一个地址,但不确定该地址起始的类型长度,void 不能运算。
l void *是一种类型,是一种无任何类型的指针。
六、 指针与函数
1. 用指针给函数传递参数
int i , j;
void display( int * a , int *b );
…
i=5; j=10;
display( &i , &j );
2. 传递数组给形参指针
void sum1(int ary1[ ],int n); //编译器将int ary1[]解释为int *类型的指针
void sum2(int *ary1 , int m);
…
int a[10]={……};
sum1(a,10); sum2(a,10);
void sort1( char c1[ ] , int i );
void sort2( char *c2 , int j );
char name[100]={……}; //等价于 char *name=”……”;
sort1(name,100);
sort2(name,100);
3. 返回指针的函数
可以返回堆地址,全局/静态变量地址,但不能返回局部变量地址!
int *fun()
{ int a[10];
…
return a; }
void main()
{ int *p;
p=fun(); } //ERROR!
七、 命令行参数
main()由操作系统调用,返回到操作系统。
void main(int argc,char *argv[ ]);
argc:指出命令行上的参数个数;
argv:指针数组,其每个元素分别指向这些参数;
八.指针常用于以下情形:
1.函数参数
用指针作为函数参数有两个好处:1)可以避免按值传递参数带来的空间浪费,2)可以通过指针间接修改形式参数所指向的地址空间。
2.字符串
就是字符指针(和字符数组一样),字符串非常常用。
3. 动态空间申请
很多时候,要使用的内存空间在设计程序无法知道(如需要用户输入),需要在运行过程中,通过new来动态申请空间,new返回的就是指针。动态申请的空间可以是简单数据类型,也可以是数组、结构或是类等复杂数据类型。
4. 链表结构
指针通常和结构一起使用,组成链表、树、图等各种复杂的数据结构。这些结构对于描述各种现实问题非常有用。
(二)引用
一、 引用的声明
类型 变量名;
类型 & 引用名;
exp: int a; int &b=a;
1. 引用不是用作函数参数或返回值时,声明必须初始化。
2. 引用不是变量,对引用的存储都是对它引用的变量的存储。
3. 引用的初始化值必须是一个变量。
l 如果是对一个常量的引用,编译器要建立临时变量:
const int num=50;