首页 > 其他分享 >二维数组和数组指针数组的关系

二维数组和数组指针数组的关系

时间:2024-11-09 11:46:12浏览次数:3  
标签:test1 int 地址 二维 数组 printf 指针

在深入理解指针end中,我在最后写了一长段代码

#include<stdio.h>
void test1(int arr[][5], int x, int y)
//void test1(int(*p)[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			//printf("%d ", *(*(p + i) + j));
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}
void test2(int* p[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", p[i][j]);
			//printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int arr1[5] = { 1,2,3,0,0 };
	int arr2[5] = { 4,5,6,0,0 };
	int arr3[5] = { 7,8,9,0,0 };
	int arr4[3][5] = { {1,2,3,0,0},{4,5,6,0,0},{7,8,9,0,0} };
	int* (p[3])[5] = { arr1,arr2,arr3 };
	test1(arr4, 3, 5);
	test2(p, 3, 5);
	return 0;
} 

现在我们来拆解一下这段代码。

1:理解二维数组的本质

二维数组就是多个一维数组的集合,元素就是一维数组。

二维数组数组名是第一行一维数组的地址,是第一行数组的地址,也是是第一行一维数组里面第一个元素的地址!!!!

如图

2:理解数组指针数组的本质

数组指针数组是一个数组,数组里面的元素是数组指针。

数组指针,就是存放数组的指针。

我们来层层破茧,来慢点理解其本质

先理解一维数组和指针的关系,也就是数组指针和数组的关系

如图

数组指针的打印的地址和一维数组的地址一样。

我们数组指针数组,就是把上面的三个数组指针放到数组里面。

如图可看,p1,2,3在数组指针数组打印的地址不是一维数组的地址了。

p1,2,3也是变量,是变量就要开辟新的内存。所以我们打印的是p,1,2,3所占的地址

如图可看

数组arr4也是新开辟的也由属于他自己的内存,但是我图上没画。

记住,是变量就要开辟空间,指针变量也是变量

但是我们可以借助*接引用来直接实现arr4中打印一维数组的地址

电脑中每一次打印地址是会变的

于此我就讲解完了,数组指针数组,数组指针的本质。

3:二维数组和数组指针数组的关系

二维数组,可以看出多个一维数组的集合

数组指针数组,可以看成多个数组指针的集合

而一维数组首元素的地址一般都代表整个指针的地址。我们在进行数组指针变量初始化是,也可以看成是把首元素的地址放在了数组指针变量中。

4:分析代码

由此我们开始理解最开始的代码

int main()
{
	int arr1[5] = { 1,2,3,0,0 };
	int arr2[5] = { 4,5,6,0,0 };
	int arr3[5] = { 7,8,9,0,0 };
	int arr4[3][5] = { {1,2,3,0,0},{4,5,6,0,0},{7,8,9,0,0} };
	int* (p[3])[5] = { arr1,arr2,arr3 };
	test1(arr4, 3, 5);
	test2(p, 3, 5);
	return 0;
} 

我定义了,一个二维数组arr4和一个数组指针数组p[3]

这个数组指针数组的类型是int*()[5]。

我们向函数传递的是数组,传递的是数组,传递的是数组!!!!

现在我们来分析test1和test2函数

1:test1

void test1(int arr[][5], int x, int y)
//void test1(int(*p)[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			//printf("%d ", *(*(p + i) + j));
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

我们传递的是arr4数组,数组是,一个五列元素的一维数组集合起来的。是非常正常的打印二维数组的方式。

我们看//部分的代码

void test1(int(*p)[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
	printf("\n");
}

这个是直接使用指针来接收二维数组,p是一个指针,指针类型是int () [5];

通过解引用p我们可以逐次访问二维数组

*(p+i)表示访问第一行的元素,也是访问第一行的首元素地址

*(*(p+i)+j)表示访问第i行的第j个元素,因为+j就是将指向首元素的地址往后移动j个单位

2:test2

void test2(int* p[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", p[i][j]);
			//printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}

这个就是直接接收的数组指针数组,p表示的是数组,数组元素的类型是int* [5]的

打印我们可以直接使用二维数组的打印方式,都是数组了,推理一下也就可以直接使用数组常规的打印方式。

看//部分

//部分是用指针来打印的,逻辑和test1差不多。

*(p+i),是把p这个数组名当成了数组首元素的地址。

单独的一个数组名是可以当首元素的地址,这个结论是前面说过的。

标签:test1,int,地址,二维,数组,printf,指针
From: https://blog.csdn.net/2403_87752060/article/details/143634130

相关文章

  • 【数据结构】快慢指针探秘:理解链表与数组中的环结构
    在处理链表或数组时,我们经常需要在一次遍历中找到特定的位置或检测某种模式。这时,快慢指针技术就能成为强大的工具,尤其在链表面试题中。本文将详细介绍什么是快慢指针、它们的工作原理,并通过一些实际应用帮助你理解这种技巧。学完后,你将掌握这种技巧的核心以及如何在代码中......
  • Air780E软件指南:C语言内存数组(zbuff)
    一、ZBUFF(C内存数组)简介zbuff库可以用c风格直接操作(下标从0开始),例如buff[0]=buff[3]可以在sram上或者psram上申请空间,也可以自动申请(如存在psram则在psram进行申请,如不存在或失败则在sram进行申请)。操作里面的元素时,可以根据光标进行增删改查。偏移方式有三种:从头......
  • 面向对象基础(2)对象数组、重载与可变个数形参
    3、对象数组数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用类型中的类时,我们称为对象数组。案例;定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。问题一:打印出4年级(gra......
  • c语言--数组
    目录1数组创建 1.1定义定长数组1.2定义并初始化数组1.3定义部分初始化的数组2.动态数组(动态分配)2.1使用malloc动态创建数组2.2使用calloc动态创建数组2.3动态数组初始化2.4释放动态数组内存3.变长数组(VLA,VariableLengthArray)4.字符串和字符数组4.1.......
  • byte数组转16进制,二进制字符串
    1)16进制字符串a)c#内置apibyte[]bytes=BitConverter.GetBytes(123);varhexStr=BitConverter.ToString(bytes); b)实现1///返回低字节顺序十六进制字符串(低字节在左侧)publicstaticstringToHexString(byte[]bytes){char[]hexChars="012345678......
  • 力扣88.合并两个有序数组
    为了将nums2的数放到nums1后面,可以将nums1的m个数和nums2的n个数进行比较,按照从大到小的顺序从右向左放入nums1中。最后输出的数组共有m+n个元素,所以最后一个元素的下标为k=m+n-1。每次k--,都要num1[m[和nums2[n]比较,大的数放到nums1[k],同时m--或n--。因为m与n不一定相等,所以......
  • 前端入门一之JS对象、字符串对象、数组对象、Data()对象等
    前言JS是前端三件套之一,也是核心,本人将会更新JS基础、JS对象、DOM、BOM、ES6等知识点,这篇是JS常用的内置对象;这篇文章是本人大一学习前端的笔记;欢迎点赞+收藏+关注,本人将会持续更新。文章目录目录总览1、对象1.1、创建对象(object)利用字面量创建对象对象的调用变量......
  • 240. 搜索二维矩阵 II(中)
    目录题目法一、暴力法二、二分查找法三、Z字形查找题目编写一个高效的算法来搜索mxn矩阵matrix中的一个目标值target。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。法一、暴力varsearchMatrix=function(matrix,target){......
  • Leetcode 474 dp数组讲解和滚动数组优化
    474.一和零​ ​dp[i][w1][w2]:DP数组的集合:考虑前i个物品包括第i个,满足背包重量不超过[w1][w2]的所有集合把输入数组中的每个string当作是一个物品,其重量分别为string中0和1的个数属性:价值每个物品的价值是1因为我们求最大子集的个数,一个字符串对子集个数贡献的......
  • C++ 函数对象、函数指针与Lambda表达式
    C++函数对象、函数指针与Lambda表达式函数指针函数指针(FunctionPointer)是指向函数的指针变量。它可以存储函数的地址,并通过该指针变量来调用该函数。函数指针的声明使用指针符号,指向的类型为函数的返回类型和参数列表,如int(funcPtr)(int,int);。函数指针的值可以指向相同......