跟周立功学C语言编程:如何将二维数组作为函数参数传递?这三要素要时刻谨记!
年之中的工作时间,使用下面这个"数组的数组"表示:
int working_time[12][31];
在这里,如果开发一个根据一个月的工作时间计算工资的函数,可以象下面这样将某月的工作时间传递给这个函数:
calc_salary(working_time[month]);
其相应的函数原型如下:
int calc_salary(int *working_time);
这种技巧只有通过"数组的数组"才能实现,而多维数组则显得苍白无力。
>>> 2. 二维数组的行
由于C语言是按行主序存储二维数组的,即先存储0行的元素,接着存储1行的元素,依此类推。因此要访问数组中的每一个元素,可以从data[0][0]开始,用一个for循环改变行,用另一个for循环改变列,详见程序清单 1.34。
程序清单 1.34 求二维数组中元素的和范例程序
1 int sum(int (*pData)[2], int size)
2 {
3 int total = 0;
4
5 for(int row = 0; row < size; row++)
6 for(int col = 0; col < 2; col++)
7 total += pData[row][col];
8 return total;
9 }
当使用指向数组的指针对data进行初始化时:
int (*pData)[2] = data;
它使pData指向data的第一行,当pData与一个整数相加时,该整数值首先根据2个整数值的长度进行调整,然后再执行加法,因此可以使用这个指针一行一行地在data中移动。
对于每个row值,内部的for循环将遍历所有的col值。如果将二维数组当作一维数组来看,则上述的双重循环可以改为单循环。比如,将二维数组的所有元素初始化为0:
for(int *ptr = &data[0][0]; ptr <= &data[row - 1][col - 1]; ptr++)
*ptr = 0;
当循环开始时,ptr指向data[0][0],ptr++使ptr指向data[0][1]、data[0][2]……当ptr到达data[0][col-1](即第0行的最后一个元素)时,再次对ptr自增使它指向data[1][0],持续这一过程直到ptr越过data[row-1][col-1](数组中的最后一个元素)为止。
如何处理二维数组一行中的元素?如果需要一个指针逐个访问数组的元素,而不是逐行在数组中移动,再次选择使用指针变量ptr。为了访问第i行的元素,需要初始化ptr使其指向数组data中第i行的元素0。即:
ptr = &data[i][0];
由于data[i]等价于*(data + i),因此&data[i][0]等同于&(*(data[i]+0)),即等价于&*data[i]。又由于&与*运算符可以抵消,因此等同于data[i],即可将"ptr = &data[i][0];"简写为:
ptr = data[i];
下面的循环是对数组data的第i行清0,其中用到了这一简化。即:
int data[row][col];
for(ptr = data[i]; ptr < data[i] + col; ptr++)
*pData = 0;
因为data[i]是指向数组data第i行的指针,所以将data[i]传递给需要用一维数组作为实参的函数,即使用一维数组的函数也可以使用二维数组中的一行。显然找到一维数组中最大元素的iMax函数,同样也可以用于确定二维数组data中第i行的最大元素:
largest = iMax(data[i], col);
>>> 3. 二维数组的列
由于数组是按行而不是按列存储的,因此处理二维数组的一列中的元素相对来说就复杂一些。下面的循环是对数组data第i列清0:
int data[row][col], (*pData)[col], i;
for(pData = &data[0]; pData < &data[row]; pData++)
(*pData)[i] = 0;
在这里,将pData声明为指向长度为col的整型数组的指针,pData++将pData移到下一行的开始位置。
- 电源软启动的实用设计技巧(07-16)
- 周立功:动态分布内存——malloc()函数与calloc()函数(07-22)
- 周立功“程序设计与数据结构”:深度解剖动态分布内存的free()函数与realloc()函数(07-25)
- 周立功教你学程序设计技术:做好软件模块的分层设计,回调函数要这样写(07-30)
- 周立功教你学C语言编程:教你数组是如何保存指针的(07-31)
- 算法的泛化问题,这些坑你可能都经历过!|周立功教你学软件设计(08-01)