微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 多维数组与指针

多维数组与指针

时间:12-01 来源:互联网 点击:

简要的说明一下,为什么会产生段错误吧,由于a是一个指向指针的指针,那么a[i]则是一个指针,他指向一个数据空间,由于数组名实际上对应一个地址,这个地址和&A等都是相同的,a[i]实质上是就是数组中的一个元素,但是其中的内容也是一个指针,这时候再次解引用就很有可能导致内存非法访问,产生段错误。比如A[2][3]={{1,2,3},{4,5,6}}。调用函数print_array(A,2,3)时,由于A实质上是一个地址,由于数组的特殊性,具有&A,A,A+0,&A[0][0]等对应的值是相同的。a = A,实质上a就是一个地址。这个地址就是数组的起始位置。a中的内容实质上就是数组的元素,因此对数组进行一次解引用(*a)得到的实质上就是数组的一个元素,也就是1,但是a是指向指针的指针,内容1也是一个地址,对地址1的访问肯定发生错误,因为地址1处是属于内核,不能直接进行访问,发生了段错误。这也就是为什么说二维数组和指向指针的指针之间并不是等价的。

但是根据上面的分析,我们知道二维数组的数组名指明了数组的位置,这时候直接对位置进行访问就能够得到数组的元素。同时我们知道a++指向的地址恰好就是a+4。刚好也就是数组的下一个元素。因此我们可以采用解一次引用的方式实现数据的访问。因此上面的代码可以修改如下,这种方法是运用了指针加法的一些特性,也就是指向指针的指针的增长大小就是大小等于4,但是这种方法只能针对类型大小为4的数组问题,其他的类型不能运用。

int print_array(int **a, int row, int col)
{
int i = 0 , j = 0;
for(i = 0; i < row; ++ i)
{
for(j = 0; j < col; ++ j)
printf("%d ",*(a+i+j));
printf("");
}
}

字符串数组是比较常用的,字符串数组定义如下:

char *str[]={
"One",
"Two",
"Three",
"Four"
};

字符串数组允许出现锯齿形的数组,也就是说各个字符串的长度可以是不相同的,我们知道字符串数组实质上是一个指针数组,和二维数组之间存在一定的差别,并不是同一种类型的问题,指针数组可以转换为指向指针的指针的问题。
我们常见的主函数main的两种种定义方式为:

int main(int argc, char *argv[])
int main(int argc, char **argv)

这两种定义方式使得很多的初学者认为二维数组和指向指针的指针有一定的联系,特别是第2种写法存在很大的误导性,实质上字符串数组和二维数组之间存在很大的差别,所以不能当做一类问题来讨论。

二维数组作为函数的形参时也是一个应该注意的问题。我们已经知道二维数组不是指向指针的指针这个结论。那么如果需要传递一个二维数组时又该如何处理呢?我们知道数组名是一个指向数组的指针,将参数设置为这种形式即可:

int print_array(int (*p)[N],int row, int col);
int print_array(int a[M][N],int row, int col);

上面的两种定义方式是比较常见的,当然也可以采用指向指针的指针这种方式,这种方式一般在动态分配二维数组的情况下使用。这时候的动态分配的二维数组和我们当前讨论的二维数组存在差别,更像是字符串指针数组问题。

/*C++*/
void array_create(int **array, int row, int col)
{
int i = 0, j = 0;

array = new int *[row];

for(i = 0; i < row; ++ i)
{
array[i] = new int[col];
}
}

其中array首先分配行,然后行中保存了指针变量,这样就实现了二维数组的动态分配,这时候的二维数组不再是线性表,这是需要注意的。在C语言中也可以直接创建线性表,即采用一维数组访问。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top