指针
-
数据对象的地址与值
地址:数据对象的存储位置在计算机中的编号
值:在该位置处存储的内容
地址与值是辩证统一的关系 -
指针的定义与使用
a. 指针的定义格式
格式:目标数据对象类型* 指针变量名称;
示例一:定义p为指向整数的指针int* p;
示例二:定义p为指向结构体类型的指针 struct POINT{int x, y;}; POINT *p;
b. 多个指针变量的定义
示例三:int *p, q;
示例四:typedef int PINT; PINT p, q; -
指针变量的存储布局
指针数据对象(变量)与目标数据对象(变量)
a. 仅定义指针变量,未初始化
示例一:int* p;
b. 定义指针变量,并使其指向某个目标变量
示例二:int n=10; int *p=&n;
c. 定义指针变量,并使其指向数组首元素
示例三:int a[8]={1, 2, 3, 4, 5, 6, 7, 8}; int *p=a;
-
指针变量的赋值
指针变量可以像普通变量一样赋值
示例:int n =10; int *p=&n, *q;q = p;
-
取址操作符
a. 取址操作符“&”
获取数据对象的地址,可将结果赋给指针变量
示例:int n =10; int *p=&n, *q;q = p;
b. 引领操作符
获取指针所指向的目标数据对象
示例一:int m, n=10; int *q=&n;m=*q;
使得m为10
示例二:*q = 1;
使得n为1
c. 整数互换程序#include <iostream> using namespace std; int main() { int m=10, n=20, t; int *p=&m, *q=&n; cout<<"m:"<<m<<";n:"<<n<<endl; t=*p; *p=*q; *q=t; cout<<"m:"<<m<<";n:"<<n<<endl; return 0; }
d. 整数互换程序
编写程序,使用指针互换两个整数的值#include <iostream> using namespace std; int main() { int m=10, n=20, *t; int *p=&m, *q=&n; cout<<"m:"<<m<<";n:"<<n<<endl; t=p; p=q; q=t; cout<<"m:"<<m<<";n:"<<n<<endl; return 0; }
-
指针的意义与作用
a. 作为函数通信的一种手段
使用指针作为函数参数,不仅可以提高参数传递效率,还可以将该参数作为函数输出集的一员,带回结果。
b. 作为构造复杂数据结构的手段
使用指针构造数据对象之间的关联,形成复杂数据结构
c. 作为动态内存分配和管理的手段
在程序执行期间动态构造数据对象之间的关联
d. 作为执行特定程序代码的手段
使用指针指向特定代码段,执行未来才能实现的函数
指针与函数
数据交换函数
常量指针与指针常量
返回指针的函数
示例一:数据交换函数
#include <iostream>
using namespace std;
void Swap(int*x, int*y);
int main()
{
int m = 10, n=20;
#ifndef NDEBUG
cout << "main(before swapped):m="<<m<<";n="<<n<<endl;
#endif
Swap(&m, &n);
#ifndef NDEBUG
cout << "main(after swapped):m="<<m<<";n="<<n<<endl;
#endif
return 0;
}
void Swap(int *x, int*y)
{
int t;
if(!x||!y)
{
cout<<"Swap:Parameters illegal."<<endl;
exit(1);
}
#ifndef NDEBUG
cout << "Swap(before swapped):*x="<<*x<<";*y="<<*y<<endl;
#endif
t=*x;
*x=*y;
*y=t;
#ifndef NDEBUG
cout << "Swap(after swapped):*x="<<*x<<";*y="<<*y<<endl;
#endif
}
-
常量指针与指针常量
实际上可以把const当作左结合
a. 常量指针:指向常量的指针
性质:不能通过指针修改目标数据对象的值,但可以改变指针值,使其指向其它地方
示例一:int n=10;const int p=&n;
典型使用场合:作为函数参数,表示函数内部不能修改指针所指向目标数据对象值
示例二:void PrintObject(const intp);
b.指针常量:指针指向的位置不可变化
性质:不可将指针指向其它地方,但可以改变指针所指向的目标数据对象值
示例三:int n = 10; int *const p=&n;
指针常量和其它常量一样,必须在定义时初始化
c. 常量指针常量:指向常量的指针常量(指针的双重只读属性)
性质:指针值不可改变,指向的目标数据对象值也不可改变
示例四:const int n=10;const int * const p=&n;
典型使用场合:主要作为函数参数使用 -
指针与函数返回值
指针类型可以作为函数返回值
函数内部返回某个数据对象的地址
调用函数后将返回值赋值给某个指针
特别说明:不能返回函数内部定义的局部变量地址(可以返回全局变量或者输入参数)
示例:int global=0; int *ReturnPointer() { return &global; }
-
指针与数组
a. 数据对象地址的计算
数组定义:int a[8] = {1, 2, 3, 4, 5, 6, 7,8};
数组基地址:&a或a
数组元素地址:
数组首元素地址:&a[0]
数组第i元素地址:&a[0] +i * sizeof(int)
数组基地址与首元素地址数值相同,故
数组第i元素地址:a+i*sizeof(int)
b. 指针运算
1)希望表达p、q之间的联系:他们都指向同一数组中的元素
2)指针与整数加减运算:设p为指向整数数组中某元素的指针,i为整数,则p+i表示指针向后滑动i个整数,p-i表示指针向前滑动i个整数。
示例一:p指向a[0],则p+2指向a[2]
示例二:p指向a[3],则p-2指向a[1]
3)指针与整数加减运算的结果仍为指针类型,故可赋值:
示例三:p指向a[0],则q=p+2使得q指向a[2]
4)指针与整数加减运算规律:以指针指向的目标数据对象类型为单位,而不是以字节为单位
5)指针的递增递减运算:
示例四:p指向a[0],则p++指向a[1]
示例五:p指向a[1],则–p指向a[0]
6)指针减法运算:两个指针的减法运算结果为其间元素个数
示例六:p指向a[0],q指向a[2],q-p结果为2
7)可以测试两个指针是否相等
示例一:设p、q为指针,则p==q测试两个指针是否指向同一个目标数据对象
8)空指针NULL
指针值0:表示指针不指向任何地方,表示为NULL
示例二:设p为指针,则p=NULL表示p不指向任何地方
示例三:(测试指针p是否有意义)if(p!=NULL)等价于if§
使用指针前一定要测试其是否有意义
c. 指针与数组的可互换性
1)互换情况:指针一旦指向数组的基地址,则使用指针和数组格式访问元素时地址计算方式是相同的,此时可以互换指针与数组操作格式
示例一:int a[3]={1, 2, 3}; int *p=&a; int i; //可以将指针p当作数组来处理 for(i=0;i<3;i++) { cout<<p[i]<<endl; } //可以将数组a当作指针来处理 for(i=0;i<3;i++) cout<<*(a+i)<<endl;
2)例外情况:数组名为常数,不能在数组格式上进行指针运算
示例二:
int a[3]={1, 2, 3};
int *p=&a; int i;
//可以将指针p当作数组来赋值
for(i=0;i<3;i++)
{
cout<<*p++<<endl;
}
//不可以将数组a当作指针来赋值 a++=>a=a+1
for(i=0;i<3;i++)
cout<<*a++<<endl;
- 指针与结构体
a. 指向结构体的指针对象
struct STUDENT
{
int id;
STRING name;
int age;
};
STUDENT student={2007010367, "Name", 19};
STUDENT *pstudent = &student;
b. 访问指针所指向的结构体对象的成员
必须使用括号:选员操作符优先级高于引领操作符
(*pstudent).id=2007010367;
(*pstudent).name=DuplicateString("Name");
(*pstudent).age=19;
c. 选员操作符“->“
pstudent->id=2007010367; //不用书写括号
d. 结构体成员类型为指针
struct ARRAY{unsigned int count;int *elements;};
int a[8]={1, 2, 3, 4, 5, 6, 7, 8};
ARRAY array={8, &a};
e. 访问指针类型的结构体成员
访问elements的第i个元素:array.elements[i]
若有定义:ARRAY* parray=&array;
访问parray指向的结构体对象elements的第i个元素:(*parray).elements[i]或parray->elements[i]
f. 结构体指针的使用场合
1)使用指向结构体对象的指针作为函数参数
2)构造复杂的数据结构