指针与二维数组

本文探讨的是如何通过指针访问二维数组中的元素,以及二维数组如何在内存中存储

指向一维数组的指针:

我们先来看下如何通过指针访问一维数组

#include <stdio.h>

int main(){
	int arr[] = {4, 3, 2, 1};
    // 由于数组名是第一个元素的指针,对数组名进行解引用(*arr:此操作称为解引用)就能拿到第一个元素
	printf("*arr=%d  arr[0]=%d\n", *arr, arr[0]);
    // 对指针+1就能拿到第二个元素的指针,依次类推
	printf("*(arr+1)=%d  arr[1]=%d\n", *(arr+1), arr[1]);
    
	return 0;
}
二维数组的存储形式:

c中的二维数组其实是一维数组的线性扩展,二维数组在内存中其实是以一维的形式存储。

比如:int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}} 在内存中的存储格式如下:

arr[0]arr[1]arr[2]

⇓ \Downarrow

123456789101112
指向二维数组的指针:

在c语言中我们可以把二维数组看作一维数组来处理,只不过这个数组的元素也是数组。比如:arr[3,4] 我们可以认为这个数组由三个一维子数组构成,而这三个一维数组都包含了4个元素

在一维数组中数组名就是第一个元素的指针,当我们将二维数组看作一个一维数组时,我们就可以推出:数组名是前n个元素组成的数组的指针(arr[3][4] n的值就是4)

请看下面例子:

#include <stdio.h>

int main(){
    int arr[3][4] = {0};
    printf("sizeof(int):%d\n", sizeof(int));	//sizeof(int):4
    printf("arr:%p",arr);		// arr:000000000062FDE0
    printf("arr+1:%p",arr+1); 	// arr+1:000000000062FDF0
    
    return 0;
}

在这里插入图片描述

地址结果相减我们可以得出10,但这是16进制的结果,转为10进制结果就是16。由于int类型占4个字节,我们可以得出arr与arr+1相差了4个元素,把二维数组的看作一维数组那么这里元素之间的跨度就是4个元素(4*4=16个字节)由此得出 arr 指向的是第一个子数组的指针,arr+1 指向的是第二个子数组的指针 …

既然 arr 指向的是第一个子数组的指针,那么 *arr(解引用) 的值就是第一个子数组的地址,更确切的说 *arr 是第一个子数组的第一个元素的地址,只有 **arr (双重解引用)才能拿到第一个子数组的第一个元素的值。

我们看如下代码:

#include <stdio.h>

int main(){
	int arr[3][4] = {
		{1,2,3,4},
		{5,6,7,8},
		{9,10,11,12}
	};
    
    // 打印结果发现 *arr == &arr[0][0],又一次证明arr指向“第一个子数组”
	printf("*arr = %p  &arr[0][0] = %p\n", *arr, &arr[0][0]);
    
	printf("**arr = %d  arr[0][0] = %d\n", **arr, arr[0][0]);
	printf("*(*arr+1) = %d  arr[1][0] = %d\n", *(*arr+1), arr[0][1]);
	printf("**(arr+1) = %d  arr[0][0] = %d\n", **(arr+1), arr[1][0]);
    
	return 0;
}

这样的做法就是通过指针来拿数组中的元素,与下标获取数组元素的结果是一致的。

测试题:

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

// 输出下面的结果
printf("*(*(arr+1)+1) = %d\n", *(*(arr+1)+1) );
printf("*(*(arr[2])+1) = %d \n",*(*(arr[2])+1) );

参考文章:http://c.biancheng.net/view/2022.html
视频:小甲鱼《带你学c带你飞》系列课程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值