C++学习路线,计划和根据实际情况的探索性实践,第三篇,深入了解指针的各种的用法

一,指针初始化时,最好赋上初值NULL/0

在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。
所以我们定义指针时,可以随手赋上一个初始值NULL/0,这样这个指针指向了一个不可访问的地址

void testPtr_01()
{
	int* p = NULL;
	cout << "p = " << p << endl;
	if (p)
	{
		cout << "p为true" << endl;
	}
	else {
		cout << "p为false" << endl;
	}
}

int main()
{
	testPtr_01();
}

为什么说NULL/0呢?
因为再宏里面可以看到,NULL就是0

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

执行结果:
在这里插入图片描述

二:指针的++,–

指针的++不是加一,而是根据指针本身的类型,比如说,指针是double类型的:那么每次++增加8,效果如下:
在这里插入图片描述

二:指针的指针,多级指针和二维数组
void testPtr_04()
{
	int var;
	int* ptr;
	int** pptr;
	var = 3000;

	// 获取 var 的地址
	ptr = &var;

	// 使用运算符 & 获取 ptr 的地址
	pptr = &ptr;
	cout << **pptr << endl;
}

int main()
{
	testPtr_04();
}
更加深入的理解

当然了,这只是菜鸟上基本的例子,下面介绍一下从大神那里抄来的深入讲解指针的,为了深入学习贯彻落实党和国家对我们新一代年轻人的要求,我毅然决定,不粘贴复制,一字一字的抄一遍:
csdn原文

  • 二维数组和指针
    要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识,我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素是,这个存储的二维数组也就变成了一个一维数组了。而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组都是一个一维数组
    下面我们讨论指针和二维数组元素的对应关系,清楚了二者之间的关系,就能用指针处理二维数组了。
    设p是指向二维数组a[m][n]的指针变量,则有:
    int* p = a[0]
    此时p指向一维数组的指针,p++后,p指向a[0][1]
    设p1为
    int (*p1)[n] = a则p1指向的是以一维数组为元素的一维数组,所以p1++后指向a[1][0]
    由于a[0],a[1],a[2],···,a[M-1]等各个行数组连续存储,则对于a数组中任意元素a[i][j]有:
    *(p+i*N+j)这个理解起来比较简短,从第一个元素累加,内存连续,就不解释了
    *(*(p1+i)+j)p1指向的是一维数组的第一个元素的头个元素,所以*(p1+i)指向的是第i+1行的头个元素的地址,+j之后,由于会自动判断类型,所以会指向第i+1行,第j+1列的元素
    例如,有如下定义:
    int a[3][4]={{10,20,30,40,},{50,60,70,80},{90,91,92,93}};
    则数组a有3个元素,分别为a[0]、a[1]、a[2]。而每个元素都是一个一维数组,各包含4个元素,如a[1]的4个元素是a[1][0]、a[1][1]、a[1]2]、a[1][3]。
    若有:
    int p=a[0];
    则数组a的元素a[1][2]对应的指针为:p+1
    4+2
    元素a[1][2]也就可以表示为:( p+14+2)
    用下标表示法,a[1][2]表示为:p[14+2]
    特别说明:
    对上述二维数组a,虽然a[0]、a都是数组首地址,但二者指向的对象不同,a[0]是一维数组的名字,它指向的是a[0]数组的首元素,对其进行“
    ”运算,得到的是一个数组元素值,即a[0]数组首元素值,因此,a[0]与a[0][0]是同一个值;而a是一个二维数组的名字,它指向的是它所属元素的首元素,它的每一个元素都是一个行数组,因此,它的指针移动单位是“行”,所以a+i指向的是第i个行数组,即指向a[i]。对a进行“”运算,得到的是一维数组a[0]的首地址,即*a与a[0]是同一个值。当用int *p;定义指针p时,p的指向是一个int型数据,而不是一个地址,因此,用a[0]对p赋值是正确的,而用a对p赋值是错误的。这一点请读者务必注意。

  • 用二维数组名作地址表示数组元素
    另外,由上述说明,我们还可以得到二维数组元素的一种表示方法:对于二维数组a,其a[0]一维数组由a指向,a[1]数组由a+1指向,a[2]数组由a+2指向,以此类推。因此,a与a[0]等价,(a+1)与a[1]等价,(a+2)与a[2]等价,···,即对于a[i]数组,由(a+1)指向。由此对于数组元素a[i][j],用数组名a的表示形式为:
    *(*(a+i)+j) 指向该元素的指针为*(a+i)+j数组名虽然是数组的地址,但它和指向数组的指针变量完全不相同
    第一:指针变量的值可以改变,即它可以随时指向不同的数组或同类型的变量,而数组名自它定义时起就确定下来,不能通过赋值的方式使该数组名指向另外一个数组。
    “我不得不说,没有C语言的基础,学起来还挺吃力的,比如说这个,怎么会有这样的结果?以前在java里面,只要是数组,我还不是想让他指谁它就指谁,但是C++里面完全不一样了,数组不能改变指向,如下图所示”
    在这里插入图片描述
    第二:数组名是指针,类型是指向元素类型的指针,但值是指针常量,声明数组时编译器会为声明所指定的元素保留内存空间。数组指针是指向数组的指针,声明指针变量时编译器只为指针本身保留内存空间
    求二维数组元素的最大值,这个能完全理解,基本上就稳了。

void testPtr_07()
{
	int a[3][4] = { {3,17,8,11},{66,7,8,19},{12,88,7,16} };
	int* ptr, max;
	for (ptr = a[0], max = *ptr; ptr < a[0] + 12; ptr++)
	{
		if (max < *ptr)
			max = *ptr;
	}
	cout << max << endl;
}
  • 行数组指针
    在上面的说明中我们已经知道,二维数组名是指向行的,它不能对如下说明的指针变量p直接赋值:
    int a[3][4]={{10,11,12,13},{20,21,22,23},{30,31,32,33}},*p;
    其原因就是p与a的对象性质不同,或者说二者不是同一级指针。C语言可以通过定义行数组指针的方法,使得一个指针变量与二维数组名具有相同的性质。行数组指针的定义方法如下:
    数据类型 (指针变量名)[二维数组列数];
    例如,对上述a数组,行数组指针定义如下:
    int (*p)[4];
    它表示,数组
    p有4个int型元素,分别为(*p)[0]、(*p)[1]、(*p)[2]、(*p)[3] ,亦即p指向的是有4个int型元素的一维数组,即p为行指针
    此时,可用如下方式对指针p赋值:
    p=a;

  • 指针数组的定义

void testPtr_08()
{
	int* p[5];
	//结果为20,int大小为4,4*5=20
	cout << sizeof(p) << endl;
}

  • 二级指针
void testPtr_09()
{
	int** ptr;
	int* p;
	int val = 10;
	p = &val;
	ptr = &p;
	cout << **ptr << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值