博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数组与指针
阅读量:5258 次
发布时间:2019-06-14

本文共 3152 字,大约阅读时间需要 10 分钟。

一维数组:
1.数组名做实参时,传递的是地址,数组名代表数组第一个元素的首地址;
2.函数形参使用指针变量用来承载数组的地址时,该形参只是地址,不是地址,sizeof(形参)得到的是指针的长度4;
3.函数用数组地址做参数时,函数内部求不出数组的大小;

C/C++中二维数组和指针关系分析:https://blog.csdn.net/zhouxuguang236/article/details/12256321

其实,在C/c++中没有所谓的二维数组,书面表达就是数组的数组,猜想是为了表述方便才叫它二维数组。

一、二维数组一维化

其实我这里也只是表述的方便才叫这么一个题目,我们怎么利用一个数组的访问方式来访问二维数组呢?下面来看一个具体的例子。

首先,定义一个二维数组。

int iArr[2][3]={0,1,2,3,4,5};
我们可以用一个指向int型的指针变量来访问这个数组,下面的代码是将数组一维化:
int* p = iArr[0];
上面的iArr[0]就是代表第一个数组的首地址,由于二维数组在内存中的存储也是先行后列的方式,所以第二行也紧跟第一行之后,这样就可以用p来访问数组的元素值了,访问的方式有下标和指针方式。

printf("%d,",p[3]);

printf("%d\n",*(p+3));
最后输出的结果都是3。讲完了一维化之后,下面来继续看二维数组的函数名到底是什么意思?
二、关于二维数组名的探索
我们可以打印出一些地址看看:
printf("iArr = %d,iArr[0] = %d,&iArr[0][0] = %d,iArr[0][0] = %d",iArr,iArr[0],&iArr[0][0],iArr[0][0]);
从结果可以看出:
二位数组名iArr 首行地址 iArr[0] &iArr[0][0]三个地址相等;
&Arr 代表整个数组首地址,加1代表加整个数组大小
Arr &Arr[0] 代表第一行首地址,加1代表加整行的大小
Arr[0], *a ,&a[0][0]代表第一行首地址,加1代表加一个元素的大小
其实iArr二维数组名是一个数组指针,数组指针是指向一个数组首地址的指针,它实际上也是一种指针类型,类似于函数指针。它声明如下:

int (*pArr)[3]

它说明pArr是一个数组指针,它指向的是一个数组元素为int类型并且数组元素的个数为3的一个数组指针,奇怪,中间的怎么还有一个括号是啥玩意?呵呵,这个括号还真是不可少的。少了它就变为另外一种类型了:指针数组。指针数组是数组类型,代表数组的每一个元素是指针类型,它声明如下:
int *pArr[3]。
大小:
sizeof(iArr)=24,
sizeof(iArr[0]) = 12;
sizeof(iArr[0][0]) = 4;
既然二维数组的数组名是指向第一行数组的首地址,我们也叫它行指针。那么我们可以用这种数组名或者指针来访问二维数组的元素。
int (*pArr)[3] = iArr;
下面,我要访问第一行第二列的元素,我可以用下面的代码来访问
*(*(pArr+1) + 2)
也可以用数组名来访问:
*(*(iArr+1) + 2)
首先,pArr是一个指向数组的指针,在这个指针上加减一个整数都是移动整行,而不是一个元素。比如说,pArr+1代表的现在指针已经指向第一行元素了,也就是实际中的第二行,而要取得指针所指的对象,就要用到解引用运算符*,所以*(pArr+1)就代表第一行数组,是整个这一行元素就取到了,那现在要取这一行的第二个元素,只须将指针再移动两个元素,即*(iArr+1) + 2,这样就指向了这个元素的地址,再解引用取得元素的值即可。
三、作为函数参数 (将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的 ,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的)

一维数组名作为函数参数实际上是退化为指针,二维数组作为函数参数又有什么不同呢?在用二维数组名作为参数传递时容易出现Segmention Error。这是因为不能正确为二维数组中元素寻址的问题,正确的方法如下:

[cpp] view plaincopy

#include <stdlib.h>

#include <stdio.h>
#define N 4
void testArray(int *a, int m, int n)
{
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
{
printf("a[%d][%d] = %d\n", i, j, *(a+i*n+j));
}
}
int main()
{
int a[2][N] = {
{1, 2, 3, 4}, {5, 6, 7, 8}};
testArray((int *)a, 2, N);
}

 

1. 将二维数组的两个维度用变量的形式传递过去

如下所示:
[cpp] view plaincopy

#include <stdlib.h>

#include <stdio.h>
#define N 4
void testArray(int **a, int m, int n)
{
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
{
printf("a[%d][%d] = %d\n", i, j, *((int*)a + i * n +j));
}
}
int main()
{
int a[2][N] = {
{1, 2, 3, 4}, {5, 6, 7, 8}};
testArray((int **)a, 2, N);
}

此时在子函数中不能使用a[i][j]的形式访问数组元素,因为数组元素都是顺序存储,地址连续,在使用a[i][j]访问数组元素时,无法顺序访问到指定的元素,所有我们只能通过计算指定所要访问的元素。

2、用指向一维数组的指针变量,如下例子所示:

[cpp] view plaincopy

#include <stdlib.h>

#include <stdio.h>
#define N 4
void testArray(int (*a)[4], int m, int n)
{
for(int i = 0; i < m; ++i)
for(int j = 0; j < n; ++j)
{
printf("a[%d][%d] = %d\n", i, j, *(*(a+i)+j)); //printf("a[%d][%d] = %d\n", i, j, a[i * n +j]);
}
}
int main()
{
int a[2][N] = {
{1, 2, 3, 4}, {5, 6, 7, 8}};
testArray(a, 2, N);
}
int (*a)[N] 表示指向一维数组的指针变量,即a所指向的对象是含有4个整型元素的数组。注意 () 不能少,若定义成:

int *a[N] 则表示有一个一维数组a[N],该数组中的所有元素都是 (int *)类型的元素。

在这里,在子函数中访问二维数组中的元素可以用 a[i][j] 或者 *(*(a+i)+j)
在这种情况下(*(a+i))[j],a [i * n +j]);,*(*(a+i)+j),a[i][j],*((int*)a + i * n +j)都可以进行访问。

转载于:https://www.cnblogs.com/llqi/p/9157941.html

你可能感兴趣的文章
python metclass
查看>>
python-Struct模块
查看>>
Python--列表-,元组,字典的介绍
查看>>
广播接收者
查看>>
Git之本地仓库
查看>>
Eureka的工作原理以及它与ZooKeeper的区别
查看>>
应用Python来计算排列中的逆序数个数
查看>>
2017前端面试题总结
查看>>
Http GetPost网络请求
查看>>
SWIFT国际资金清算系统
查看>>
关于拷贝构造函数与赋值构造函数的深刻解析
查看>>
Sping注解:注解和含义
查看>>
站立会议第四天
查看>>
用原生JS获取非行间样式
查看>>
toolbox类
查看>>
如何快速掌握一门技术
查看>>
利用AMPScript获取Uber用户数据的访问权限
查看>>
C语言本身并不提供输入输出语句
查看>>
Go used as value问题
查看>>
vagrant 同时设置多个同步目录
查看>>