真正理解C++中数组名和指针之间的关系

前言

自己琢磨问题的时候更喜欢在代码里面写记录,反而不喜欢在MarkDown记录,每次会将完整版源码放在最后,其实源码前面的内容我也不是很想写

C++中的数组

随手写了,可能有概念上的错误,大多也是大白话,毕竟自己也是小白,说不了多么高大尚的话语,通俗易懂就是最好的。

  • 数组
    数组:是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。它可以存储一个固定大小相同类型元素顺序集合

  • 一维数组的声明方式:

// 1.使用未初始化的内存,不会补0
type arrayName [ arraySize ];

// 2.使用初始化的内存,会补0
type arrayName [ arraySize ] = {};	// 会有 arraySize 个 0
type arrayName [ arraySize ] = { val1, val2 ...};	// 没有定义的话会自动补 0

// 3.长度会依据输入的数据个数而定
type arrayName[] = { val1, val2 ...};

不再讲二维的原因是,我想快点讲指针。

  • 数组名
cout << arr << endl;	// 可以直接查看 arr数组 首地址 // 十六进制
cout << (int)arr << endl;	// 可以直接查看 arr数组 首地址 // 十进制
cout << &arr[0] << endl;	// 查看 arr数组 第一个数据的 首地址
// arr数组 首地址 == arr数组 第一个数据的 首地址

在此你会发现,数组名好像就是一个指针,的确,在此很明确的告诉你,数组名就是一个指针,指向的就是数组第一个数据的首地址。

  • 注意:
    数组名一旦创建,就是一个常量,指向一个首地址,因此不能够再进行赋值,会报错。

指针

在此直接说结论吧,具体请看最后的源代码,里面更为详细。

指针分为很多种,这是介绍两种,地址均用十进制表示,不带类型的指针和带类型的指针。

  • 不带类型的指针

假如一个指针是 p,指向一个地址:100;
那么p++;后,指针的地址会指向:101;
换句话说,p指向100,p+1指向的就是101;

加深理解,不带类型的指针就是一个 int,这个int指向就是内存地址

  • 带类型的指针

众所周知,1个字节(Byte)有8个字符(Bit),…当我没说,我说这个干嘛

重来:
一个内存地址(例如100)就对应一个字节,有很多数据类型都不止一个字节,比如32位系统中一个int型占4个字节,64位系统中一个int型占8个字节。

以32为系统为例,每四个字节代表一个整数,那么如果采用指针来获取数据,每次就需要+4对否,当然这里指的是不带类型的指针,但是我们就会认为+1就应该取下一个整数,这么人性化的需求当然是要满足的呀。

所以C++提供了带类型的指针。
如果是int型指针,换个字母,ip,这个ip是一个int型指针,指向的地址是100,如果ip+1,你觉得应该指向多少?它就是指向了104
带类型的指针+num,就是+num*(类型所占字节大小),因此如果能分别指针的类型,那么就很容易理解数组名和数组指针之间的关系了,包括一些面试题,也不在话下了!

数组名和指针

  • 直接上结论

创建一个数组int b[] = {1,2,3};,数组名b就是一个指针,指向这个数组的首地址,解指针就会获取数组的第一个数*b*(b+1)就会获取数组的第二个数哟。

注意区分*(b+1)*b+1
*(b+1):是指针移到数组第二个数的首地址然后解指针获取到2这个数
*b+1 :是指针数组第一个数的首地址被解压获取到1这个数然后 1+1 =2,怎么一样了?怪我例子没举好,再来一遍!

创建一个数组int a[] = {10,20,30};,数组名a就是一个指针,指向这个数组的首地址,解指针就会获取数组的第一个数*a*(a+1)就会获取数组的第二个数哟。

注意区分*(a+1)*a+1
*(a+1):是指针移到数组第二个数的首地址然后解指针获取到20这个数
*a+1 :是指针数组第一个数的首地址被解压获取到10这个数然后 10+1 =11

  • &a

int a;创建一个整型对象a&a就是取a对象的地址,也就是指向a的指针
如果是数组int a[] = {10,20,30};呢?在此不深入追究,a本身就是一个带类型的int指针了,&a就是将a指针变为a这整个对象的指针,也就是说(&a+1) == a+sizeof(a)/sizeof(a[0])

源代码

// 数组中的指针:对象指针和元素指针
void array_index_001()
{
	int b[] = { 1,2,3,4,5 };
	cout << "查看一下array的内存地址:" << &b << endl;
	// 但是b也是可以创建array的地址的
	cout << "直接用数组变量名查看地址:" << b << endl;
	
	// 但是这两个指针是有区别的
	//	&b 是对象 b 这整个对象的(起始)地址;
	//	b 是对象 b 中第一个元素的地址;
	//	如何验证:分别将两个地址+1,既可以看出区别
	cout << "对象指针+1结果:" << &b + 1 << endl;
	cout << "元素指针+1结果:" << b + 1 << endl;
	//	一个相差 20 一个相差 4,;因此对元素取址,多用数组变量名
	//	加深理解,其实变量名b 相当于 &b[0]
	cout << "验证&b[0]+1:" << &b[0] + 1 << endl;
	cout << "---" << endl;
	//	换成整数看更为直观
	cout << "换成整数看更为直观" << endl;
	cout << "查看一下array的内存地址:" << int(b) << endl;
	cout << "对象指针+1结果:" << int(&b + 1) << endl;
	cout << "元素指针+1结果:" << int(b + 1) << endl;
	cout << "验证&b[0]+1:" << int(&b[0] + 1) << endl;
}

// 数组中的指针:剖析数组索引
void array_index_002()
{
	int a[] = { 1,2,3,4,5 };
	// 分别看看输出:a、a[0]、a+1、a[1]
	cout << "a: " << a << endl;
	cout << "a[0]: " << a[0] << endl;
	cout << "a+1: " << a+1 << endl;
	cout << "a[1]: " << a[1] << endl;
	// 可以得出怎样的结论呢?
	//	数组名就是一个指针,a 和 a+1 均输出的是元素的地址
	//	我们换一个方式来输出同样的内容
	cout << "---" << endl;
	cout << "使用纯指针来输出同样的结果" << endl;
	cout << "a: " << a << endl;
	cout << "*a: " << *a << endl;
	cout << "a+1: " << a + 1 << endl;
	cout << "*(a+1): " << *(a+1) << endl;
	//由此可见:a[num] 其实就是 *(a+num)	// 指针偏移后取索引
	//			a[0] 其实就是 *(a+0) 也就是 *a
	//	python中a[-1]就是最后一个数,可以负数索引,C++中可以吗?
	//cout << "---" << endl;
	//cout << "看看负索引是个啥 a[-1]: " << a[-1] << endl;
		看来是未初始化的空间:-858993460
		虽然能运行,但是编译器已经把我给“绿了”,所以弄懂就OK了
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacob-xyb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值