C++基础知识(四)

指针

  1. 数据对象的地址与值
    地址:数据对象的存储位置在计算机中的编号
    值:在该位置处存储的内容
    地址与值是辩证统一的关系

  2. 指针的定义与使用
    a. 指针的定义格式
    格式:目标数据对象类型* 指针变量名称;
    示例一:定义p为指向整数的指针int* p;
    示例二:定义p为指向结构体类型的指针 struct POINT{int x, y;}; POINT *p;
    b. 多个指针变量的定义
    示例三:int *p, q;
    示例四:typedef int
    PINT; PINT p, q;

  3. 指针变量的存储布局
    指针数据对象(变量)与目标数据对象(变量)
    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;
    在这里插入图片描述

  4. 指针变量的赋值
    指针变量可以像普通变量一样赋值
    示例:int n =10; int *p=&n, *q;q = p;
    在这里插入图片描述

  5. 取址操作符
    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;
    }
    

    在这里插入图片描述

  6. 指针的意义与作用
    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
}
  1. 常量指针与指针常量
    实际上可以把const当作左结合
    a. 常量指针:指向常量的指针
    性质:不能通过指针修改目标数据对象的值,但可以改变指针值,使其指向其它地方
    示例一:int n=10;const int p=&n;
    典型使用场合:作为函数参数,表示函数内部不能修改指针所指向目标数据对象值
    示例二:void PrintObject(const int
    p);
    b.指针常量:指针指向的位置不可变化
    性质:不可将指针指向其它地方,但可以改变指针所指向的目标数据对象值
    示例三:int n = 10; int *const p=&n;
    指针常量和其它常量一样,必须在定义时初始化
    c. 常量指针常量:指向常量的指针常量(指针的双重只读属性)
    性质:指针值不可改变,指向的目标数据对象值也不可改变
    示例四:const int n=10;const int * const p=&n;
    典型使用场合:主要作为函数参数使用

  2. 指针与函数返回值
    指针类型可以作为函数返回值
    函数内部返回某个数据对象的地址
    调用函数后将返回值赋值给某个指针
    特别说明:不能返回函数内部定义的局部变量地址(可以返回全局变量或者输入参数)
    示例:

    int global=0;
    int *ReturnPointer()
    {
    	return &global;
    }
    
  3. 指针与数组
    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;
  1. 指针与结构体
    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)构造复杂的数据结构

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值