二维数组地址

二维数组定义:

int arr[2][3];
typedef p arr[3];
p *q;
二维数组在内存中地址存储顺序:

for (size_t i = 0; i < 2; i++)
	{
		for (size_t j = 0; j < 3; j++)
		{
			//数组地址线性增长,可能是arr[0][0],arr[0][1]。。。。也可能是arr[0][0],arr[1][0]
			//本例是先行后列
			printf("value:%d, address:%p\n", tempArr[i][j], &tempArr[i][j]);
		}
	}
	printf("-------------------------\n");


	//value:1, address:010FF770
	//value:2, address:010FF774
	//value:3, address:010FF778
	//value:4, address:010FF77C
	//value:5, address:010FF780
	//value:6, address:010FF784
二维数组做参数:

void address(int (*tempArr)[3])
{


	for (int i = 0; i < 2; i++)
	{
		printf("tempArr:%p\n",tempArr[i]);
		printf(("&tempArr:%p\n"), &(tempArr[i]));
		for (size_t j = 0; j < 3; j++)
		{
			printf("value:%d ", tempArr[i][j]);
		}
		printf("\n");
	}
	//tempArr:0073FD8C
	//&tempArr:0073FD8C
	//value : 1 value : 2 value : 3
	//tempArr : 0073FD98
	//&tempArr : 0073FD98
	//value : 4 value : 5 value : 6

}

int main()
{
	int arr[2][3] = { { 1,2,3 },{ 4,5,6 } };

	address(arr);

	system("pause");
    return 0;
}
int (*tempArr)[3]此处等同于int tempArr[][3]

int *tempArr[3]为一个一维数组,数组中每个元素都是指针。

为什么参数可以写成int tempArr[][3],而不可以写成int tempArr[2][];

语法上:tempArr理解成一个指针,必须告诉指针指向的类型int [3]。

个人理解:这么写带来一个额外的好处,可以通过传参截取数组任意位置,任意长度的连续元素。如int temp[0+1][3];

tempArr每次+1 步长为指向元素类型的大小,此处为int*3.

关于上段代码中tempArr和&tempArr,地址相同的理解(如果有误,欢迎指出):此处没有额外申请空间,tempArr可以理解成指针,但是没有单独为指针申请空间,本身存储的就是指向元素的地址,即第一组元素首元素地址,和第二组元素首元素地址(有误,待纠正)


区别于上,附上一段指针申请额外空间的代码(此处代码原地址http://blog.youkuaiyun.com/zqxnum1/article/details/40592737);

#include <stdio.h>  
  
typedef char p[3];  
  
  
int main(){  
      
    char ch[2][3];  
    printf("%d\n%d\n%d\n%d\n",&ch,ch[0],&ch[0],&ch[0][0]);  
    printf("\n");  
  
    p *q = new p[2];  
    printf("%d\n%d\n%d\n%d\n",&q,q[0],&q[0],&q[0][0]);  
      
  
    return 0;  
}  

输出结果如下:


q 本质上还是个指针,是个变量,它自身位于栈区,但是它的内容是某个二维数组的地址,换言之,它的内容与 ch 等价, 但是 q 不是 ch, 这就是编译器对待指针形式的数组与 直接形式的数组的不同之处, q 作为一个变量,自身也要存在内存的某个位置,而符号“q”就是这个位置的代号,而 ch 直接就是某块内存的首地址的代号。





### 二维数组的内存地址分布原理 在32位系统中,二维数组的内存地址分布方式与其存储结构密切相关。二维数组本质上是由多个一维数组组成的,其存储机制可以分为两个层次:外层数组和内层数组。 在外层,JVM首先为二维数组分配一个一维数组的空间,这个一维数组存储的是各个内层数组的引用。这些引用指向各自独立的一维数组,每个一维数组则存储实际的数据元素。例如,在声明`int[][] twoDArray = new int[3][4];`时,JVM会先分配一个长度为3的一维数组来保存三个内层数组的引用,随后分别为这三个内层数组分配各自的内存空间,每个内层数组的长度均为4[^1]。 从内存地址的角度来看,外层一维数组中的每个元素实际上是一个指针,它指向了对应内层数组的起始地址。这意味着,虽然外层一维数组和内层数组都位于堆内存中,但它们之间通过指针相互连接。因此,当访问`twoDArray[0][0]`时,程序会先找到外层一维数组的第一个元素所指向的内层数组的起始地址,再根据索引定位到具体的元素位置[^2]。 对于未指定具体大小的二维数组(如`int[][] arr = new int[3][];`),JVM同样会为外层一维数组分配内存空间,并将所有内层数组的引用初始化为null。此时,只有当用户显式地为每个内层数组分配内存(如`arr[0] = new int[4];`)后,该内层数组才会拥有自己的内存空间和相应的引用地址[^3]。 此外,需要注意的是,尽管上述讨论主要围绕Java语言展开,但其他支持多维数组的语言(如C/C++)也有类似的实现机制。不过,由于不同编程语言对内存管理的具体实现可能存在差异,所以在处理多维数组时的具体行为也可能有所不同。 ```java // 示例代码:展示如何动态分配二维数组的内存 public class Main { public static void main(String[] args) { int[][] dynamicArray = new int[3][]; // 声明一个不指定列数的二维数组 // 动态分配每一行的内存 for (int i = 0; i < dynamicArray.length; ++i) { dynamicArray[i] = new int[i + 1]; // 每一行的长度可以不同 } // 打印数组内容以验证是否正确分配内存 for (int row = 0; row < dynamicArray.length; ++row) { for (int col = 0; col < dynamicArray[row].length; ++col) { System.out.print(dynamicArray[row][col] + " "); } System.out.println(); } } } ``` 这段示例代码展示了如何在Java中动态地为一个二维数组分配内存,其中每行的长度可以根据需要进行调整。通过这种方式,即使是在创建时不指定完整的维度信息,也可以灵活地构建出符合需求的数据结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值