前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一维数组/二维数组的取地址和指针

一维数组/二维数组的取地址和指针

作者头像
黎鹤舞
发布2024-03-19 15:13:03
920
发布2024-03-19 15:13:03
举报

一维数组

一维数组的数组名

在一维数组中,数组名通常指代的就是数组的首地址。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//一维数组:
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n",*arr);
	printf("%d\n",*arr+1);
	return 0;
}

对数组名进行解应用操作,会显示一维数组的第一个元素。对解应用的数组名进行+1操作,会向后跳转一个字符类型的空间, 即为arr[ 0 ] ~ arr[ 1 ]


一维数组的取地址操作

在有些时候,我们想得到整个数组的地址。比如说在结构体中,我们想要跳过整个数组。对数组进行取地址操作,可以取整个数组的地址。 但是有人在测试的时候会发现,如果我直接对 打印 &数组名 和 普通打印数组名的地址显示一样,那么我们来测试一下。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//一维数组:
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	
	printf("%p\n", arr);
	printf("%p\n", arr + 1);
	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);

	return 0;
}

输出结果:

可以看到虽然输出arr 和 &arr 的地址信息相同,但是对其进行+1操作时,两者跳过的地址空间完全不同。 arr跳过的是 4 字节 而 &arr 跳过的是 40 字节

二维数组

二维数组的数组名

二维数组的数组名 和 一维数组的数组名有点差别,我们经常用一维数组的思维,想当然的认为二维数组的数组名是整个数组的第一个元素的地址。但是二维数组可以看作是一个一维数组,其数组内的每一个元素都是一个数组。 所以二维数组数组名就是对应的一维数组的首元素,即二维数组第一行的元素。 我们对其进行测试

发现*(aa + 1)比*aa 大了20个字节,正好对应五个int类型字节长度。

  • 注:这里不能写成*aa + 1 会变成对aa先解应用,再进行+1(int类型字节长度)的操作,输出的结果就会变成00BBFBE8了 *

取地址操作符 &

二维数组的 & 操作符和一维数组很相似,都表示的是整个数组的地址。二维数组就表示的是二维数组的地址。 引入一块代码进行测试:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//二维数组和指针
int main()
{
	int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };

	printf("&aa is %p\n",&aa);
	printf("(&aa+1) is %p\n",&aa + 1);

	return 0;
}

我们对二维数组aa进行 & 操作,输出其地址信息,然后对其进行++操作;结果如下:

经计算,发现D0-A8 = 28, 即十进制的40。正好是整个二维数组的长度(4 byte * 2 * 5)。

其实我们在vs调试上也能直接看到 &aa 指的是整个二维数组的地址。

知识点巩固

学到了知识点就要加以练习,请思考下列代码的输出结果:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

题目分析

首先,aa是一个二维数组,其数据类型为 int [ 2 ] [ 5 ]。 &aa = 整个数组的地址,取完地址进行 + 1,表示的是向后跳一个int类型字节长度的地址。该处地址信息由指针变量 ptr1 进行存储;再对ptr1 进行 -1操作,因为ptr 1的类型是int 类型指针,所以 -1 操作是跳过了 一个int 类型的字节,即为 数组最后一个元素 a[ 9 ] 。 所以第一个值输出的是 1

其次是(aa + 1) ,aa是二维数组的数组名,代表的是二维数组第一行的元素。 所以(aa + 1)表示的是二维数组第二行元素的地址。

在调试窗口可以验证:

同理, -1 操作是跳过了 一个int 类型的字节,所以从aa[1] [ 0] 跳转到了aa[0][4]。结果是6

输出结果如图:

关于*aa

这里特别特别注意 *aa 有的人可能会问,对于ptr 2的赋值,为什么是 (int)(*(aa+1));* 因为

  • 如果是一维数组,*a [ 0 ]可以直接得到a[ 0 ]的值
  • 但是对于二维数组,*aa[ 0 ] 得到的仍是一个地址

但是我们有时候会需要 aa[ 0 ]的具体值,该怎么办呢?

  • 我们需要用一个指针变量接受 *aa[ 0 ]的值, 因为 * aa[ 0 ]虽然表示的是第一行元素的地址,但是指针变量接收到的 还是 * aa[0] 第一个元素的地址。
  • 对指针变量进行解应用( * )就可以得到*aa[ 0 ]的值

那么为什么 *aa得到的仍然是一个地址呢?

我们可以这样理解,aa[row] [col] 其实是一个一维数组,但是每一个数组包含 col 个地址信息,只有打开每个数组包含着的地址信息,才是一个数据,所以对aa解应用,只解开了第一层包装,里面的仍是包含了一组地址信息。

总结

对于一维数组: *p == *a; 对于二维数组: *p != *aa;

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一维数组
    • 一维数组的数组名
      • 一维数组的取地址操作
      • 二维数组
        • 二维数组的数组名
          • 取地址操作符 &
          • 知识点巩固
            • 题目分析
              • 关于*aa
                • 总结
            相关产品与服务
            腾讯云服务器利旧
            云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档