C语言 二维数组作为函数参数的4种方式

本文介绍C语言中二维数组作为函数参数的4种传递方式,包括数组形式、指针形式、变长数组等,并通过实例代码展示了每种方式的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

多维数组中,二维数组是最常用的一种。在C语言编程中,二维数组的定义、取值以及赋值都比较容易,与一维数组类似。然而,在将二维数组作为函数参数传递时,参数结构较复杂,难以理解。本文章是实用型文章,注重代码使用,不会讲述过多理论。如果想要学习理论知识(非常推荐,可以对代码的理解更透彻),可以查阅下方参考文献列出书籍的第10章内容。话不多说,下面将给出一个C程序,以展示二维数组作为函数参数的4种方式。注:下面的代码已在VS Code(使用Mingw64)和VS 2015下编译运行过。

正文

下面程序的功能是对一个int型二维数组的所有元素进行求和,并分别把求和结果打印在屏幕上。根据二维数组传入函数的方式,定义了4个版本的求和函数。

#include <stdio.h>

#define ROW 2   //二维数组的行数
#define COL 2   //二维数组的列数

//4个版本的求和函数
//方式一:数组形式
int TwoDimArraySum1(int twoDimAr[][COL], int row, int col);

//方式二:指针形式,prArray是一个指向包含COL个int的数组的指针
int TwoDimArraySum2(int (*prArray)[COL], int row, int col);

//方式三:指针形式,pr是一个指向int的指针
int TwoDimArraySum3(int *pr, int row, int col);

//方式四:变长数组(C99开始支持)
int TwoDimArraySum4(int row, int col, int twoDimAr[row][col]);

int main(void)
{
    int twoDimArray[ROW][COL] = {{-2, 5}, {4, 9}};
    int result;

    //方式一
    result = TwoDimArraySum1(twoDimArray, ROW, COL);
    printf("Sum1函数结果:%d\n", result);

    //方式二
    result = TwoDimArraySum2(twoDimArray, ROW, COL);
    printf("Sum2函数结果:%d\n", result);

    //方式三
    result = TwoDimArraySum3(twoDimArray[0], ROW, COL);
    printf("Sum3函数结果:%d\n", result);

    //方式四
    result = TwoDimArraySum4(ROW, COL, twoDimArray);
    printf("Sum4函数结果:%d\n", result);

    return 0;
}

int TwoDimArraySum1(int twoDimAr[][COL], int row, int col)
{
    int i, j;
    int result = 0;

    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            //下面两种寻址方式都行
            result += twoDimAr[i][j];
            // result += *(*(twoDimAr + i) + j);
        }
    }
    return result;
}

int TwoDimArraySum2(int (*prArray)[COL], int row, int col)
{
    int i, j;
    int result = 0;

    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            //下面两种寻址方式都行
            result += prArray[i][j];
            // result += *(*(prArray + i) + j);
        }
    }
    return result;
}

int TwoDimArraySum3(int *pr, int row, int col)
{
    int i, j;
    int result = 0;

    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            //下面两种寻址方式都行
            result += pr[i*col + j];
            // result += *(pr + i*col + j);
        }
    }
    return result;
}

int TwoDimArraySum4(int row, int col, int twoDimAr[row][col])
{
   int i, j;
   int result = 0;

   for (int i = 0; i < row; i++)
   {
       for (int j = 0; j < col; j++)
       {
           //下面两种寻址方式都行
           result += twoDimAr[i][j];
           // result += *(*(twoDimAr + i) + j);
       }
   }
   return result;
}

 正如程序注释所言,方式4(变长数组)是C99开始支持的,不是所有编译器都支持。例如,VS 2015就不支持该语法。因此,在VS 2015环境下运行时,方式4被注释了。下面给出VS Code(基于Mingw64)以及VS 2015环境下的运行结果。

                                                                         左图为VS Code;右图为VS 2015

优缺点评价

这里先给出结论,最推荐使用方式3。下面是简要的分析。

  • 方式1和方式2实质上是相同的。它们适用性很好。但是,它们定义必须事先给出第二维的长度,即不是对任意大小的二维数组都适用。
  • 方式3适用性同样很好,对任意大小的二维数组都适用。但是,它是最难理解的。理解它需要对二维数组元素的结构、二维数组元素的储存以及二维数组与指针的关系有比较深刻的理解。
  • 方式4是最容易理解的了。但是,它的适用性最差。

最后需要强调的是,对于该程序的求和函数,更安全、更易读的写法是将参数列表中接受二维数组数据的参数加上const修饰。本程序没加的原因是为了更好的突出其功能。const修饰的对象不同,产生的效果也不同。如果参数列表中接受二维数组数据的参数加上const修饰,它将无法修改二维数组的数据;如果只有待传入的二维数组是用const修饰,参数列表中的参数不是const修饰的,那么上述方式都不被允许。因此,请根据实际情况,自行决定const的修饰对象和修饰位置。

关于更高维数组

对于更高维的数组,上面四种方式仍然适用。除了方式3外,另外三种方式都很容易扩展成更高维的。对于方式3,虽然最推荐它,但是它随着维数的增多,它变得更复杂更难理解。而且基于方式3,还可以延伸出其他方式。这里以三维数组举例,方式3还可以延伸出这样一种方式,该方式中接受三维数组的形参是一个指向一维数组的指针。对于这种由方式3延伸的方式,我是不推荐的,它比方式3更复杂,使用它还不如使用方式3。

参考文献

Stephen Prata写的《C Primer Plus》第五版

博主:虔诚~似锦(主博客)

个性签名:如果你愿意努力,人生最坏的结果也不过是大器晚成。

------------------------------------------------------------------------------------

如果这篇文章对你帮助的话,记得在下方点赞哦,博主在此感谢!🎉🎉🎉

如果对这篇文章有疑问,请在评论区指出,欢迎探讨,共同进步。😄😄😄

### C语言中定义接受二维数组作为参数的函数 在C语言中,当需要定义一个接收二维数组作为参数的函数时,可以通过两种常见的方式来声明形参。一种方法是指定完整的维度大小(除了最左边那一维),另一种则是通过指针表示法。 对于指定尺寸的方法而言,假设有一个`m×n`的整型二维数组,则可以在函数原型以及实现部分如下所示: ```c // 方法一:显式说明每一列的数量 void processArray(int matrix[][n], int rows); ``` 这里的关键在于保持第二维(即每行内的元素数量)不变,并将其具体数值提供给编译器以便正确解析内存布局[^1]。 而采用指针方式表达相同逻辑会显得更加灵活一些,尤其是在处理不同宽度的矩阵时尤为有用: ```c // 方法二:利用指向固定长度的一维数组的指针 void processArray(int (*matrix)[n], int rows); ``` 上述两段代码实际上是对同一概念的不同表述形式,二者均可用于传递并操作多维数据结构。值得注意的是,在实际编程实践中,通常还需要额外的一个参数来指示输入矩阵的具体规模——比如这里的`rows`变量就用来告知程序当前正在处理多少行的数据[^2]。 下面给出一段具体的例子展示如何运用这些原则编写能够正常工作的代码片段: ```c #include <stdio.h> #define COLS 3 // 列数常量定义 /// @brief 打印二维整形数组的内容 /// @param mat 输入的二维数组 /// @param row_count 数组所含有的行数 void printMatrix(int mat[][COLS], int row_count) { for (int i = 0; i < row_count; ++i) { for (int j = 0; j < COLS; ++j) printf("%d ", mat[i][j]); putchar('\n'); } } int main(void){ int myMat[2][COLS]={{1,2,3},{4,5,6}}; printMatrix(myMat,sizeof(myMat)/sizeof(myMat[0])); return 0; } ``` 这段简单的测试案例展示了如何创建一个多维数组并向自定义的功能模块传递它以执行特定的任务。在这个过程中可以看到,无论是调用方还是被调用方都严格遵循了之前提到的原则,从而确保整个过程顺利无误地完成。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值