0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

二维数组作为函数参数传递在实际中的应用

AGk5_ZLG_zhiyua 来源:未知 作者:刘勇 2017-12-20 07:19 次阅读

周立功教授数年之心血之作《程序设计与数据结构》,电子版已无偿性分享到电子工程师与高校群体,在公众号回复【程序设计】即可在线阅读。书本内容公开后,在电子行业掀起一片学习热潮。经周立功教授授权,本公众号特对本书内容进行连载,愿共勉之。

第一章为程序设计基础,本文为1.7.3将二维数组作为函数参数。

>>>>1.7.3将二维数组作为函数参数

>>>1.函数原型

当将数组的数组作为函数参数时,数组名同样视为地址,因此相应的形参如同一维数组一样也是一个指针,比较困难的是如何正确地声明一个指针变量pData指向一个数组的数组data? 如果将pData声明为指向int类型是不够的,因为指向int类型的指针变量只能与data[0]的类型匹配。假设有以下代码:

int data[3][2] = {{1, 2}, {3, 4}, {5, 6}};

int total = sum(data, 3);

那么sum()函数的原型是什么?

由于表达式中的数组名data可以被解释为指针,即data的类型为指向int [2]的指针类型int (*)[2],因此必须将pData声明为与之匹配的类型,data才能作为实参传递给sum()。其函数原型如下:

int sum(int (*pDdata)[2], int size);

当然,也可以将这个函数原型写成下面这样的形式:

int sum(int data[3][2], int size);

还有一种格式,这种格式与上述原型的含义完全相同,但可读性更强。在声明一个接收二维数组为参数的函数时,只要提供第二个即可:

int sum(int data[][2], int size);

其中,data[]表达式是数组指针的一种隐式声明,(*pData)表达式则是指针的一种显式声明。虽然data是“由2个int值组成的数组(元素个数未知)”,但它同样可以被解释为“指向int [2]的指针”。即:

int sum(int (*pData)[2], int size);

由于下标是数组类型的一部分,如果第2个方括号是空的,则数组类型就不完整了,因为编译器也不知道如何补全它。因此类似这样的声明:

int sum(int data[3][], int size);

int sum(int data[][], int size);

是错误的。

sun()函数为何将行数(3)作为参数,而不是将列(2)作为参数呢?上述原型都指出,data是指针不是数组。由于data是由2个int值组成的数组,因此也就意味着在声明时指定了列数,这就是为什么没有将列数作为独立的函数参数进行传递的原因。比如:

int data[80][3];

int total = sum(data, 20);

int total = sum(data+5, 10);

当然,也可以让函数将二维数组看成一维数组,比如,如何找到二维数组中的最大元素。其函数原型(iMax.h文件)如下:

int iMax(int *pData, size_t numData)

如果将数组的地址data作为iMax()函数的第1个实参,数组data中的元素总数量row*col作为第2个实参:

largest = iMax(data, row*col);

则无法通过编译,因为data的类型为int (*)[col],而iMax函数期望的实参类型是int *。正确的调用形式如下:

largest = iMax(data[0], row*col);

其中的data[0]指向第0行的元素0,经过编译器转换后,其类型为int *,实参与形参类型一致。当将data强制转换为(int *)data时,同样也可以求二维数组中元素的最大值,详见程序清单 1.33。

程序清单1.33求二维数组中元素的最大值范例程序

1 #include

2 #include "iMax.h"

3

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

5 {

6 int data[][2] = {{1, 2}, {3, 4}, {5, 6}};

7 int n = sizeof(data) / sizeof(data[0][0]);

8 printf("%d\n", iMax((int *)data, n));

9 return 0;

10 }

由于data[0][0]是一个int值,因此&data[0][0]的类型为int *const。即可用以下方式指向data的第1个元素,增加指针的值使它指向下一个元素。即:

int *ptr = &data[0][0];

int *ptr = data[0];

如果将某人一年之中的工作时间,使用下面这个“数组的数组”表示:

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移到下一行的开始位置。在表达式(*pData)[i]中,*pData代表data的一整行,因此(*pData)[i]选中了该行第i列的那个元素。注意,*pData必须使用括号,否则编译器会认为pData是指针数组,而不是指向数组的指针。

由此可见,只要抓住“变量的三要素(即变量的类型、变量的值和变量的地址)”并贯穿始终,则一切问题将迎刃而解。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4976

    文章

    18246

    浏览量

    287921
  • 周立功
    +关注

    关注

    38

    文章

    130

    浏览量

    37067
  • 数组
    +关注

    关注

    1

    文章

    408

    浏览量

    25593

原文标题:周立功:如何将二维数组作为函数参数传递

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    二维数组转换为RGB图像问题

    大家好,我现在是通过建立一个512×512的二维数组生成一幅黑白图像,但是现在我又要通过这个二维数组生成一个彩色图像,就是RGB图像。看到有个函数
    发表于 09-17 14:21

    数组写入二维数组

    labview如何将一数组写入二维数组某列或某行
    发表于 12-27 17:04

    labviEW中二维数组排序问题

    问题是这样的,我不断采集过来的两种参数,都是成对出现的,我把它们组成了一个二维数组,现在就想以其中的一个参数按大小排序,另一个参数不排序但是
    发表于 03-31 13:48

    labview二维数组问题

    二维数组数组每个元素又包含3个元素,将两数组比较找出一个和另一个相同或接近的元素,用labview求程序或者算法。另外一个二维
    发表于 05-04 17:25

    LABView怎样把二维数组替换到已知二维数组里边

    书中学到说为了优化内存,最好不要用创建数组函数,所以准备先建立一个数组,再用替换函数更新,现在有一个n行9列的二维
    发表于 05-09 14:43

    求解答如何生成二维数组

    我想用LabVIEW生成一个2行10列的二维数组,第一行是1到10,第行是10个随机数,然后通过写入电子表格函数保存在文件,能给我一个生
    发表于 03-15 15:53

    labview二维数组提取几行组成新数组

    想问一下大家,labview里一个二维数组通过对其中一列的元素进行阈值判断,然后将满足条件的一行提取出来,组成新的数组,用数组创建函数不是可
    发表于 02-16 17:47

    怎么将串口接收到的数据存储二维数组

    怎么将串口接收到的数据存储二维数组数组大小是定的,数据存储从第一行第一列开始,往下存储,这个程序该怎么写,我试过for循环和while
    发表于 12-10 18:51

    请问怎么修改二维数组的值,求帮助感谢

    我用5个一数组通过创建数组函数,创建了一个二维数组请问怎么把
    发表于 05-18 11:15

    C语言二维数组的定义和引用

    ], a[2][3]二维数组概念上是二维的,即是说其下标两个方向上变化,下标变量在数组
    发表于 07-12 08:55

    LABVIEW怎么将二维数组转化为一数组

    `LABVIEW怎么将二维数组转化为一数组并且如何将数据显示到波形图中... 并且如何将数
    发表于 02-14 16:56

    二维数组冒泡排序

    Labview对于一数组可以直接排序,但如果是二维数组时,特别是字符串类型二维
    发表于 09-30 16:06

    二维数组

    如图,如何得到二维数组滚动条的位置, 持续写入数据时,想让滚动条显示最新数据的位置
    发表于 01-11 17:14

    ​​​LabVIEW DLL传递一个二维数组报错

    DLL,其参数包含一个2数组。 注意:在其他应用(比如Matlab®)当需要为LabVIEW DLL传递一个
    发表于 02-19 20:44

    函数参数传递的原理

    参数传递,是在程序运行过程中,实际参数就会将参数传递给相应的形式
    的头像 发表于 03-02 11:41 6907次阅读
    <b class='flag-5'>函数</b><b class='flag-5'>参数</b><b class='flag-5'>传递</b>的原理