问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C语言数组作为函数参数的完整指南

创作时间:
作者:
@小白创作中心

C语言数组作为函数参数的完整指南

引用
CSDN
1.
https://blog.csdn.net/weixin_40162095/article/details/113992025

本文详细介绍了C语言中数组作为函数参数的各种用法,包括数组元素、数组名、二维数组以及更高维数组作为函数参数的传递方式。通过理论讲解配合代码示例,帮助读者全面理解这一重要知识点。

一:数组元素作为函数的实参

数组元素就是变量,与普通变量没有区别,将数组元素传送给形参,实现单向的值传递。用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。

在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。

#include <stdio.h>
float max(float x,float y)
{
    if(x > y)
    return x;
    else
    return y;
}
int main()
{
    int a[6] = {3,2,1,4,9,0};
    int m = a[0];
    for(int i = 1;i < 6; i ++)
    {
        m = max(m,a[i]);
    }
    printf("数组中的最大元素是:%d",m);
}

二:数组名作为函数的实参

实质是地址的传递,将数组的首地址传给形参,形参和实参共用同一存储空间,形参的变化就是实参的变化。用数组名作函数参数时,则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。当形参和实参二者不一致时,即会发生错误。在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。

那么,数据的传送是如何实现的呢?

数组名就是数组的首地址, 因此在数组名作函数参数时所进行的传送只是地址的传送,也就是说把实参数组的首地址赋予形参数组名(既然如此,那函数参数自然可以为定义成指针的形式,后续会讲)。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空间。

举例子:

上图说明了这种情形。图中设a为实参数组,类型为整型。a占有以2000为首地址的一块内存区。b为形参数组名。当发生函数调用时,进行地址传送,把实参数组a的首地址传送给形参数组名b,于是b也取得该地址2000。于是a,b两数组共同占有以2000为首地址的一段连续内存单元。从图中还可以看出a和b下标相同的元素实际上也占相同的两个内存单元(整型数组每个元素占二字节)。例如a[0]和b[0]都占用2000和2001单元,当然a[0]等于b[0]。类推则有a[i]等于b[i]。

举例说明,同时练习冒泡排序,小的数像水泡浮在上面。

#include <stdio.h>
//其中形参数组b没有给出长度,而由n值动态地表示数组的长度。n的值由主调函数的实参进行传送。
void sort(int b[], int n) 
{
    for (int i=0;i<n-1;i++)//n个数比较只需要比较n-1次,因为比较是两个数之间进行的,比如两个数比较只需要比较1次。
    {
        for (int j = 0; j < n - 1 - i; j++)
        //可以这么理解当大的数沉底后,就不再参与排序了,循环1次,找出此轮中最大的数放在该轮比较的最底部,
        //下一轮找出剩下数据中的最大值,并排到该轮最底部,排序了i次后,就有i个数退出排序,就只剩下n-1-i个数待排,这就是n-1-i的由来
        {
            if (b[j] > b[j + 1])
            {
                int temp = 0;
                temp = b[j];
                b[j] = b[j + 1];
                b[j + 1] = temp;
            }
        }
    }
}
int main()
{
    int a[6] = { 3,2,1,4,9,0 };
    sort(&a[0], sizeof(a) / sizeof(a[0]));
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d ", a[i]);
    }
    return 0;
}

关于数组作为函数参数调用的讨论

其中数组作为函数参数调用还可以写成如下形式:

sort(a, sizeof(a) / sizeof(a[0]));
sort(&a[0], sizeof(a) / sizeof(a[0]));

测试结果:

*将函数参数定义为指针的形式

可以达到同样的效果

举例:

#include <stdio.h>
void sort(int* b, int n) 
{
    for (int i=0;i<n-1;i++)
    {
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (b[j] > b[j + 1])
            {
                int temp = 0;
                temp = b[j];
                b[j] = b[j + 1];
                b[j + 1] = temp;
            }
        }
    }
}
int main()
{
    int c[6] = { 3,2,1,4,9,0 };
    sort(c,6);
    for (int i = 0; i < 6; i++)
    {
        printf("%d ", c[i]);
    }
    return 0;
}

测试结果:

关于函数定义的参数表的讨论

另外函数定义的参数表可以写成:

void sort(int b[], int n);
void sort(int b[x], int n);  //其中x≠0即可

其中x≠0即可,实际编程中写成这样也没必要,直接用void sort(int b[], int n)就行。

测试:

x=1 小于a的数组长度
x=100 大于a的数组长度
但是当x为0时,编译都无法进行:

三:二维数组名作为函数参数

第一维的大小可以不指定,第二维的大小必须指定。实参传送的是二维数组的首地址,使得二维数组a与b共用同一存储单元,即a[0][0]与b[0][0]共用同一存储单元,a[0][1]与b[0][1]共用同一存储单元。

测试:

#include <stdio.h>
//b[2][3]也正确
int max(int b[][3]) 
{
    int m = 0;
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            if (m < b[i][j])
            {
                m = b[i][j];
            }
        }
    }
    return m;
}
int main()
{
    int a[2][3] = { 3,2,1,4,9,0 };
    int sizea = sizeof(a);
    int maxVal = max(a);
    printf("max is %d ", maxVal);
    return 0;
}

注意形参二维数组的第二维必须与实参一致,否则会报错,如下图所示:

第一维除了不能为0以外,都可以,实际编程中直接与实参的维度一样,没必要制造麻烦。

*将函数参数定义为指针的形式

可以达到同样的效果

(1)第一维是指针,第二维是数组

且第二维数组的长度必须和实参的长度一样,否则调用该函数时编译无法通过

举例

#include <stdio.h>
int max(int (*b)[3], int row, int col) 
{
    int m = 0;
    for (int i = 0; i < row; i++)//sizeof(b) / sizeof(b[0])为行数
        for (int j = 0; j < col; j++)
            if (m < b[i][j])
                m = b[i][j];
    for (int i = 0; i < 2; i++)//sizeof(b) / sizeof(b[0])为行数
        for (int j = 0; j < 3; j++)
            b[i][j]=m;
    return m;
}
int main()
{
    int a[2][3] = { 3,2,1,4,9,0 };
    int maxVal = max(a,2,3);
    printf("max is %d \n", maxVal);
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

测试结果

(2)二维指针并不能达到传递普通二维数组的效果

现象:

强转也不行:

原因

参考文档

(3)只有动态申请的二维数组才可通过二维指针作为函数参数传递

代码:

int max1(int **b, int row, int col)
{
    int m = 0;
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            if (m < b[i][j]) m = b[i][j];
    for (int i = 0; i < 2; i++)
        for (int j = 0; j < 3; j++)
            b[i][j] = m;
    return m;
}
int main()
{
    int a[2][3] = { 3,2,1,4,9,0 };
    int maxVal = max(a,2,3);
    int row = 2,col = 3;
    int** a1 = new int*[row];
    for (int i = 0; i < row; i++)
        a1[i] = new int[col];
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
            a1[i][j] = (i+1)*j;
    max1(a1,row,col);
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%d ", a1[i][j]);
        }
        printf("\n");
    }
    return 0;
}

测试:

获取二维数组的行和列

获取二维数组的行和列是经常遇到的

定义一个二维数组int array[A][B],可以通过计算sizeof获取行列数。

sizeof(array[0][0])为一个元素占用的空间,

sizeof(array[0])为一行元素占用的空间,

sizeof(array)为整个数组占用的空间,

行数 = sizeof(array)/sizeof(array[0]);

列数 = sizeof(array[0])/sizeof(array[0][0]);

根本原因:

测试:

四:更高维数组作为函数参数同二维数组类似

举例

#include "conv1.h"
#include <iostream>
#include <iomanip>
using namespace std;
![](https://wy-static.wenxiaobai.com/chat-rag-image/13639077355474515759)
float max(const float conv1_weight[64][3][3][3][3]);
int main()
{
    int a[2][3] = { 0,1,2,
        3,4,5 };
    cout << a[1][2] << endl;
    cout << "numbers of conv1_weight: " << sizeof(conv1_weight) / sizeof(conv1_weight[63][2][2][2][2]) << endl;
    cout << "conv1_weight[63][2][2][2][2]: " << setiosflags(ios::fixed) << setprecision(10) << conv1_weight[63][2][2][2][2] << endl;
    cout << "max of conv1_weight: " << max(conv1_weight) << endl;
    int b = 16;
    b >>= 1;
    cout << b;
    return 0;
}
float max(const float conv1_weight[64][3][3][3][3])
{
    float max = 0;
    for (int i = 0; i < 64; i++)
        for (int j = 0; j < 3; j++)
            for (int k = 0; k < 3; k++)
                for (int m = 0; m < 3; m++)
                    for (int n = 0; n < 3; n++)
                    {
                        if (max < conv1_weight[i][j][k][m][n])
                        {
                            max = conv1_weight[i][j][k][m][n];
                        }
                    }
    return max;
}

其中conv1_weight[64][3][3][3][3]为下图所示:

测试结果:

五:参考文档

[1] http://c.biancheng.net/cpp/html/61.html
[2] https://blog.csdn.net/lishundi/article/details/87906920

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号