c语言编程学习之二维数组

作者: 博客园精华区  更新时间:2021-05-11 22:46:00  原文链接


二维数组

c语言按照行主序存储二维数组。也就是说,二维数组元素在内存中的位置是连续的,每行末尾元素(若不是最后一行)的下一个元素就是下一行的首元素。

如下图所示

接下来我们来分析一下如何将二维数组所有元素初始化零。

假设数组的声明如下:

int a[NUM_ROWS][NUM_COLS];

普通的写法是利用两层for循环

int row, col;
for (row = 0; row < NUM_ROWS; row++)
  for (col = 0; col < NUM_COLS; col++)
    a[row][col] = 0;

我们可以利用指针操作,将二维数组看成一个一维的大数组,其元素数量为NUM_ROWS*NUM_COLS,利用一个for循环完成操作

int *p;
for (p = &a[0][0]; p <= &a[NUM_ROWS-1][NUM_COLS-1]; p++)
  *p = 0;

不过虽然代码量减少了,但实际上程序运行的次数和前者两层for循环操作运行次数是一样的。(这类方法明显破坏了程序的可读性,但是至少对一些老的编译器来说这种方法在效率方面进行了补偿。不过,对许多现代的编译器来说,这样所获得的速度优势往往极少甚至完全没有。)

接下来我们再看一个例子:将二维数组第i行的元素置0

为了访问到第i行的元素,让p指向数组a中第i行的第一个元素:

p=&a[i][0];

实际上,我们还可以将这句代码简写为

p=a[i];

对于任意一维数组a[]来说,其首元素地址为a。而二维数组可以看成是多个一维数组,行数就是一维数组的个数,列数就是数组中元素的个数。由此第i行的首元素地址就为a[i]。

如果要正经推导的话:对于任意数组a来说,表达式a[i]等价于 (a + i)。因此&a[i][0]等同于&( (a[i] + 0)),而后者等价于& a[i];又因为&和 运算符可以抵消,也就等同于a[i]。

那么代码为:

int a[NUM_ROWS][NUM_COLS], *p, i;
for (p = a[i]; p < a[i] + NUM_COLS; p++)
  *p = 0;

接下来我们再来思考一下怎么将数组a的第i列的元素置零呢?

我们可以利用数组指针(指向数组的指针)来实现这点。如声明一个数组指针: int (*p)[NUM_COLS]

我们知道,c语言指针每次自增1时,内存地址增加的量即为指针指向类型的所占内存单元数。在这里,p指向一个元素个数为NUM_COLS的int型数组,那么p++将会导致p指向地址增加NUM_COLS*(int型所占地址单元个数),这就实现了p从这一行指向了下一行。

代码如下

for(p = &a[0]; p < &a[NUM_ROWS]; p++){
	(*p)[i] = 0;
}

最后,如果我们想遍历整个数组的话,也可以将整个二维数组看成一整个一维数组,利用指针进行遍历。

int *t;
for(t = a[0]; t <= &a[NUM_ROWS-1][NUM_COLS-1]; t++)
		printf("%d ",*t);