码迷,mamicode.com
首页 > 编程语言 > 详细

数组与指针

时间:2018-06-09 00:05:06      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:erro   ++   size   std   方便   对象   维度   .net   并且   


一维数组:
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)都可以进行访问。














数组与指针

标签:erro   ++   size   std   方便   对象   维度   .net   并且   

原文地址:https://www.cnblogs.com/llqi/p/9157941.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!