向函数传递数组

传地址形式传数组

数组名相当于指向数组首地址的常量指针。

对于一维数组

传地址方式传数组时,若在函数声明中数组方括号中有数字,若为正数则忽略,若为负数则报错,所以一般函数声明及定义如下:

void modifyArray(int b[], int size);
void modifyArray(int b[], int size) {
    int i = 0;
    for (; i < size; i++) {
        b[i] = 0;
    }
}

使用时如下:

int array[6];
modifyArray(array, 6);

因数组代表数组第一个元素的地址,因此用数组名作为实参就可以将数组的起始地址传递给被调函数。所以当被调函数在函数体中修改数组元素时,真正修改的是存储在原存储单元中的数组元素。也可通过如下方式声明:

void modifyArray(int *b, int size);
void modifyArray(int *b, int size) {
    int i = 0;
    for (; i < size; i++) {
        b[i] = 0;
    }
}

当遇到某些情况函数中禁止修改数组元素值时,可使用const类型限定符防止被调函数修改数组元素如下:

void printArray(const int b[], int size);
void printArray(const int b[], int size) {
    int i = 0;
    for (; i < size; i++)
        printf("%d\n", b[i]);
}

多维数组

对于二维数组,测试如下:

#include <stdio.h>

void func1(int arr[2][3]);
void func2(int arr[1][3]);
void func3(int arr[][3]);
void func4(int arr[2][2]);  //note:expected 'int (*)[2]' but argument is of type 'int (*)[3]'
void func5(int arr[2][]);   //error:array has incomplete element type
void func6(int arr[][]);    //error:array has incomplete element type

void func1(int arr[2][3]) {
    int j, k;
    printf("Function1\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

void func2(int arr[1][3]) {
    int j, k;
    printf("Function2\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

void func3(int arr[][3]) {
    int j, k;
    printf("Function3\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

void func4(int arr[2][2]) {
    int j, k;
    printf("Function4\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

void func5(int arr[2][]) {  //error:array has incomplete element type
    int j, k;
    printf("Function5\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

void func6(int arr[][]) {   //error:array has incomplete element type
    int j, k;
    printf("Function6\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    func1(arr);
    func2(arr);
    func3(arr);
    func4(arr);      //warning:passing argument 1 of 'func4' from incompatible pointer type
    func5(arr);      //error
    func6(arr);      //error
    return 0;
}

其中func5和func6不能通过编译,提示error:array has incomplete element type。
func4只有warning,提示传入数据应为int (*)[2]而不是int (*)[3]。输出结果为:

1 2 3
3 4 5

func1,func2,func3可以正常输出。
再次测试如下:

#include <stdio.h>
void func7(int (*arr)[3]);
void func8(int (*arr)[2]);  //note:expected 'int (*)[2]' but argument is of type 'int (*)[3]'
void func9(int (*arr)[]);

void func7(int (*arr)[3]) {
    int j, k;
    printf("Function7\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
void func8(int (*arr)[2]) {
    int j, k;
    printf("Function8\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
void func9(int (*arr)[]) {
    int j, k;
    printf("Function9\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);   //error:invalid use of array with unspecified bounds
        }
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    func7(arr);
    func8(arr);   //warning:passing argument 1 of 'func8' from incompatible pointer type
    func9(arr);
    return 0;
}

func7正常输出,func8输出如下:

1 2 3
3 4 5

func9无法编译通过。
再次测试如下:

#include <stdio.h>
void func10(int **arr);
void func11(int *arr[3]);
void func12(int *arr[2]);
void func13(int *arr[]);

void func10(int **arr) {
    int j, k;
    printf("Function10\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
void func11(int *arr[3]) {
    int j, k;
    printf("Function11\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
void func12(int *arr[2]) {
    int j, k;
    printf("Function12\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
void func13(int *arr[]) {
    int j, k;
    printf("Function13\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", arr[j][k]);
        }
        printf("\n");
    }
}
int main(int argc, char const *argv[])
{
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    func10(arr);
    func11(arr);
    func12(arr);
    func13(arr);
    return 0;
}

func10,func11,func12,func13编译时均warning输入数据类型不相同,运行程序时均不能正常运行。

解释如下:
对于二维数组arr,该数组有2个元素,而每个元素都是由3个int组成的数组,所以,arr的类型可以看做指向拥有3个int元素数组开头的指针。所以传递参数时形参应该声明为指向拥有3个int元素的数组的指针。即如下:

void func7(int (*arr)[3]);

等价于func1,func2,func3。func1,func2,func3其前括号的数字均被忽略。如:

void func1(int arr[2][3]);
void func2(int arr[1][3]);
void func3(int arr[][3]);

而func7中*arr外的括号并不能忽略,因为优先级[]大于*优先级,若为func11,func12,func13则表示为元素类型为int * 类型的指针数组,即为int **,与func10形参类型相同。如下:

void func10(int **arr);
void func11(int *arr[3]);
void func12(int *arr[2]);
void func13(int *arr[]);

对于func5,func6无法通过编译,编译器提示为不完整的元素类型。如:

void func5(int arr[2][]);
void func6(int arr[][]);

对于func9,并没有指明所指向的数组的界限:

void func9(int (*arr)[]);

但是传递了正确的首地址,若想正常使用,需要再func9中将其地址赋给int (*)[3]类型的指针(func10等均可如下使用),如下:

void func9(int (*arr)[]) {
    int (*a)[3] = arr;
    int j, k;
    printf("Function9\n");
    for (j = 0; j < 2; j++) {
        for (k = 0; k < 3; k++) {
            printf("%d ", a[j][k]);
        }
        printf("\n");
    }
}

func4,func8均是将int (*)[3]类型的指针赋值给了int (*)[2]的指针。如下:

void func4(int arr[2][2]);
void func8(int (*arr)[2]);

编译器首先忽略func4形参列表中arr后第一个[]内数字,认为arr为一个指向含有两个int类型元素数组的指针。
对于一个n行m列的二维数组array,单个元素大小为b个字节,其元素array[j][k]的地址计算为array + ((m * j) + k) * b,所以传二维数组时二维数组的列数不可缺少。
所以对于func4和func8,将arr看做一个指向含有两个元素数组的指针,所以arr[0][2]计算得出的元素应该是3,arr[1][0]同样计算得出的元素也是3,运算结果如下:

1 2 3
3 4 5

对于更高维的数组可以根据其地址计算方式来判断如何传入到函数中。

传值形式传数组

当结构体传递给一个函数时,是它们是传值的方式传递的,可以通过使用结构体,来按照传值的方式传递一个数组。需先创立一个以该数组为成员的结构体,然后以传值的方式传递这个结构体,这样数组就以传值的方式被传递过去。例:

#include <stdio.h>

#define SIZE 5

typedef struct
{
    int data[SIZE];
    int size;
} Array;

void modifyArray(Array);

int main(int argc, char const *argv[])
{
    int i;
    Array array;
    array.size = SIZE;
    for (i = 0; i < SIZE; i++) {
        array.data[i] = i;
    }

    modifyArray(array);

    for (i = 0; i < SIZE; i++) {
        printf("%d\n", array.data[i]);
    }
    return 0;
}

void modifyArray(Array a) {
    int i;
    for (i = 0; i < a.size; i++) {
        a.data[i] = 1;
    }
}
  • 17
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值