数组的地址与值及表示形式

本文详细解释了C语言中一维数组和二维数组的地址计算,以及如何通过地址获取值,强调了数组名、首元素地址与实际元素地址的区别。
摘要由CSDN通过智能技术生成

引言

本篇文章不讲数组的定义,只讲讲数组在内存中的地址及表现形式。如果你对数组不是那么地了解,可以先看看以下两篇博主的文章
C语言一维数组
C语言二维数组

一维数组

一维数组地址

首先我们先定义一个简单一维数组arr1[4]

int arr1[4] = {1, 2, 3, 4};

接着分别打印arr1&arr1*arr1

printf("address1 is %d.\naddress2 is %d.\nvalue is %d.\n", arr1, &arr1, *arr1);

输出:
在这里插入图片描述
从输出结果可以发现,这里的address1和address2的值是一样的。下面我们再分别打印arr1+1&arr1+1

printf("address1 is %d.\naddress2 is %d.\nvalue is %d.\n", arr1+1, &arr1+1, *arr1);

输出:
在这里插入图片描述
这时的address1和address2的值是不一样的。都是进行了+1操作,为什么两者的结果会不一致呢?这就和取地址符号&有关。

大家都知道,对于一个一维数组,数组名代表的是数组首元素的地址,在以上的例子里,这个地址就是数组名arr1对应的地址,即6422032&arr1代表的是arr1[4]这一整个数组的地址,而不是数组中某个元素的地址。

通过输出结果我们可以发现,整个数组的地址和数组首元素的地址是一样的,不同点就是两者所表示的范围不同。对于arr1,对其进行+1操作后,对应的地址是数组第二个元素的地址,即6422036。对于&arr1,对其进行+1操作后,对应的地址是该数组最后一个元素的最后一个字节的地址+1,即6422048。(在这里数组为int类型,数组每个元素占用4个字节。)

一维数组的值

分析完地址,我们来看看数组的值。运行以下代码。

printf("value1 is %d.\n", *arr1);
printf("value2 is %d.\n", *arr1+5);
printf("value3 is %d.\n", *(arr1+1));
printf("value4 is %d.\n", *(arr1+4));

输出:
在这里插入图片描述
因为arr1是数组首元素的地址,所以对arr1进行取值操作后,得到的结果为1
arr1+5表示的是1+5,即对取值操作后的数值加5。
arr1是数组首元素的地址,所以arr1+1对应的是数组第二个元素的地址,取值操作后结果为2
因为数组arr1只有四个元素,arr1+4对应的地址内容为空,并没有被定义和赋值,所以对应的输出结果为0或乱码(此处为乱码)。

接着我们再展示一段代码:

printf("value1 is %d.\n", *arr1);
printf("value2 is %d.\n", *(&arr1));

你可能会想,上文中提到了arr1&arr1的值是一样的,那对这两个值进行取值取值操作,结果肯定也是一样的吧?输出如下:
在这里插入图片描述
看到输出的结果,你可能会疑惑为什么*(&arr1)的值是一个地址。但其实你仔细观察*(&arr1)会发现,*(&arr1)相当于对arr1进行了取地址操作然后再解引用(取值),所以实际上还是arr1,而arr1表示的是数组首元素的地址,所以输出为一个地址值。

二维数组

二维数组地址

首先先定义一个二维数组

int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

在C语言中,二维数组是按行排列的,即按行排序存放。先存放 arr[0]行,再存放 arr[1] 行,接着存放 arr[2] 行。每行有 3 个元素,也是其依次存放的。在定义数组时,可以省略行,但是列不能省略。

和一维数组类似,我们先打印arr&arr的值

printf("address1 is %d\n",arr);
printf("address2 is %d\n",&arr);

输出:
在这里插入图片描述
我们可以发现和一维数组一样,arr&arr的值是相同的。接着我们打印arr+1&arr+1的值。

printf("address1 is %d\n",arr+1);
printf("address2 is %d\n",&arr+1);

输出:
在这里插入图片描述
从输出的结果我们可以发现,arr+1&arr+1的值是不一样的,这很合理,因为一维数组中的arr1+1&arr1+1的值也是不一样的。
但是仔细观察一下我们会发现,二维数组里arr+1的值和一维数组里arr1+1的值在原来基础上增加的幅度并不一样。二维数组的arr+1地址值比arr地址值增加了12,而一维数组的arr1+1地址值比arr1地址值只增加了4。
造成这个差异的原因是因为,在二维数组里,数组名代表的不再是数组首元素的地址,而是数组首行元素的地址。在这里,可以将二维数组理解为三个一维数组的组合,数组名代表的就是第一行(第一个一维数组)的地址。
而对于&arr+1&arr代表的是整个二维数组,&arr+1对应的地址跨过了整个arr数组,所以是在原地址的基础上加36。

这个时候你可能会问,数组首元素的地址要怎么表示呢?
这里直接公布其中一个答案:二维数组用*arr表示首元素的地址。
代码如下:

printf("address1 is %d\n",arr);
printf("address2 is %d\n",*arr);
printf("value1 is %d\n",*(*arr));
printf("address3 is %d\n",*arr+1);
printf("value2 is %d\n",*(*arr+1));

输出如下:
在这里插入图片描述
*arr进行加1操作后,得到的*arr+1对应的值为6422004,即数组第二个元素的地址。
二维数组的首元素地址还有另外一种表示方法,待会会提到。

对于二维数组,arr[0]arr[1]arr[2]分别表示的是第一行元素的首元素地址、第二行元素的首元素地址、第三行元素的首元素地址。&arr[0]&arr[1]&arr[2]分别表示的是整个第一行元素的地址(即{1,2,3}的地址)、整个第二行元素的地址、整个第三行元素的地址。
代码如下:

printf("address1 is %d\n", arr[0]);
printf("address2 is %d\n", arr[1]);
printf("address3 is %d\n", arr[2]);
printf("address4 is %d\n", &arr[0]);
printf("address5 is %d\n", &arr[1]);
printf("address6 is %d\n", &arr[2]);

printf("after +1 :\n");

printf("address1 is %d\n", arr[0]+1);
printf("address2 is %d\n", arr[1]+1);
printf("address3 is %d\n", arr[2]+1);
printf("address4 is %d\n", &arr[0]+1);
printf("address5 is %d\n", &arr[1]+1);
printf("address6 is %d\n", &arr[2]+1);

输出:
在这里插入图片描述

二维数组的值

代码如下:

printf("value1 is %d\n",*(*arr));
printf("value1 is %d\n",*arr[0]);
printf("value1 is %d\n",*arr[1]);
printf("value1 is %d\n",*arr[2]);
printf("value1 is %d\n",arr[0][0]);
printf("value1 is %d\n",(*arr)[0]);

输出:
在这里插入图片描述
*arr[0]*arr[1]*arr[2]表示的是第一行、第二行、第三行数组首元素的值。arr[0][0]就是最基本和直观的二维数组对应值的表示方法。由上面的内容可知*arr表示的是二维数组首元素的地址,可以和一维数组类比一下,“首元素的地址(数组名)+索引”,对应的就是数组的值,在这里*(arr)[0]表示的就是该二维数组的第一个元素,同理*(arr)[8]对应的就是该二维数组的第九个元素。

总结

C语言的数组还是很有趣的,之后有时间就来写写指针相关的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值