二维数组中的一些有趣的理解

开始之前提出一些问题,如果你能很正确的给出回答,那这篇文章对你来说没有没有意义,如果不能,那不妨往下看一看:

下面代码会输出什么或者说各个值之间有什不同(前段为代码后段为结果)

                                                                       (1)

 

(2)

(3)

                       

一.一维数组的特性

1.为什么要讲一维数组的特性

一维数组中有些特性对于解释二维数组有帮助,有必要提出来

2.特性介绍(前提都是一维数组)

(1)单独arr可表示首元素地址,在与sizeof或&符号共用时则可表示整个数组的地址:当我们用printf中的地址格式(%p)打印时,首元素地址和整个元素地址是一样的,但是我们将其+1就可以看出区别

代码如下

 为什么+1后不一样,arr作为地址加+1时移动一个步长,步长取决于地址指向的数据类型,如这里的arr指向首元素,受元素类型为int,占4个字节,故地址尾数由8变为c;而&arr代表整个数组,占了10个整形,即40个字节,故尾数从CF8(8+16*15+16*16*12=3320)变为D20(16*2+16*16*13=3360),从这里可以看出arr与&arr的区别

(2)这里写一个熟知的结论:arr[n]等价于*(arr+n),也就是说将数组名加上n后解引用将访问arr中下标为n的元素,这应该是语言规定的格式,在这里我不能做出解释,只能作为结论记住他。不过我们可以验证这一结论,验证很简单,这里不赘述了。

二.

1.解释前面所提的问题2:

不管在一维还是二维数组中arr都代表首元素地址,而二维数组中的首元素指的是第一行(这里默认大家知道这个知识点),所以arr指的是是第一行地址,*arr指的是解引用一整行的地址,然后我们得到了首元素的地址,这是通过第2个问题的代码得到的,他是问题,同时也是一种验证。通过这段代码我想得出的结论是解引用一整行将得到这一行首元素的地址,这有利于我们解释代码。(这里是通过结论得到的,并没有到原理层面的解释,很有可能是错误的,如果大家有其他见解,欢迎指正,后面的观点也是)

2.解释前面所提的问题3:

arr[0]等价于*(arr+0)这是前面在一维数组中提过的性质,在二维数组中同样适用,而*(arr+0)相当于*arr这里是解引用一整行的地址,拿到的就是该行首元素的地址,这是显然的,但是这解释不了这段代码为什么输出这个结果,&arr[0]从输出结果来看应该是代表一整行的地址,这又如何解释呢?我是这样解释的:大家还记得一维数组中的数组名吗单独用时是首元素的地址,而与&和sizeof连用时将会表示一整行的地址,这里也是这样理解的。写arr,arr+1就是为了比较这一点。

3.解释代码1:

&arr得到一整行地址*(&arr)得到该行首元素地址,很容易就解释了,为什么把它放到最后呢,是因为我们可以通过别的理解得到正确的结果。如我这样理解&和*符号相互抵消,剩下的还是arr作为首元素地址,我的水平有限,不能找出这种理解的漏洞(我认为可能的错误是我&符号是放在括号里面使用的,所以不存在抵消这种说法,也欢迎大家提出对这种理解的看法)。但是我仍建议采用第一种理解方式,因为他与我们的理论相吻合,更有助于大家形成一种有体系的思维方式。

二.也把前面的代码写了一下,我的代码都是在vs2022中写的,大家也可以在其他编译器中试验一下。

#include <stdio.h>

int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	printf("%p %p\n", &arr, *(&arr));
	printf("%p %p\n", &arr + 1, *(&arr) + 1);
	printf("%p %p\n", &(*arr), &(*arr) + 1);
	return 0;
}

int main()
{
	int arr[2][5] = { 0,1,2,3,4,5,6,7,8,9 };
	printf("%p %p\n", *(arr), *(arr)+1);                  //解引用一整行的地址得到该行首元素
    printf("%p %p\n", arr, arr + 1);
	return 0;
}
int main()
{
	int arr[2][5] = { 0,1,2,3,4,5,6,7,8,9 };
	printf("%p %p\n", &arr[0], arr);
	printf("%p %p\n", 1 + &arr[0], 1 + arr);
	return 0;
}

三.

为什么会写这篇文章呢,或者说为什么会想到这样去理解代码,因为在实际做题过程中,我遇到过很多不同的,对我来说很奇特的代码。每个人对代码有不同的解释,同一个人对不同代码的解释也往往会出现模糊的问题,甚至是自相矛盾的,这对我造成大困扰(不知道和我一样的初学者有没有这种困扰),所以我才想到要这样做,也希望能够对大家有用。

这些都是我自己对代码的一些理解,我不知道是否是正确的,但是猜测,探索,验证这一过程是很有趣的,我认为这才是学习代码的乐趣所在(我是一个新手),也希望通过发布这篇文章把我的想法拿出来给大家看一下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值