C语言--函数-数组的运用

80 阅读5分钟

在 C 语言中,数组与函数结合 是非常核心的用法,但由于数组传参的特殊性(退化为指针),需要掌握关键规则和常见场景。下面从「传参原理」「核心用法」「常见场景」三个维度详细讲解:

一、数组传参的核心原理

C 语言中数组不能直接按值传递,将数组名作为函数参数时,数组名会退化为「指向数组首元素的指针」。

  • 函数无法通过 sizeof(arr) 获取原数组的长度(只能得到指针的大小,如 4/8 字节);
  • 函数对数组元素的修改会直接作用于原数组(因为操作的是同一块内存)。

关键结论:

传递数组时,必须额外传递数组长度(除非数组以固定值结尾,如字符串的 \0)。

二、数组与函数结合的核心用法

1. 基础:函数打印数组(最常用)

目标:编写通用函数,打印任意长度的 int 数组。

c

运行

#include <stdio.h>

// 打印数组:参数1=数组指针,参数2=数组长度
void printArr(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr1[] = {1, 2, 3, 4, 5};
    int arr2[] = {7, 8, 9};
    // 计算数组长度:sizeof(数组)/sizeof(单个元素)
    int len1 = sizeof(arr1) / sizeof(arr1[0]);
    int len2 = sizeof(arr2) / sizeof(arr2[0]);

    printArr(arr1, len1); // 输出:1 2 3 4 5
    printArr(arr2, len2); // 输出:7 8 9
    return 0;
}

2. 进阶 1:函数修改数组元素

目标:编写函数,将数组所有元素乘以 2。

c

运行

// 修改数组:将每个元素×2
void multiplyArr(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        arr[i] *= 2; // 直接修改原数组(指针特性)
    }
}

int main() {
    int arr[] = {1, 2, 3};
    int len = sizeof(arr) / sizeof(int);
    
    multiplyArr(arr, len);
    printArr(arr, len); // 输出:2 4 6(原数组已被修改)
    return 0;
}

3. 进阶 2:函数返回数组(注意陷阱)

C 语言中函数不能直接返回数组,但可以通过以下 2 种方式实现 “返回数组” 的效果:

  • 方式 1:传入一个空数组,函数填充数据(推荐);
  • 方式 2:返回指向静态数组 / 动态数组的指针(注意内存泄漏)。

示例(方式 1:填充数组):

c

运行

// 填充数组:生成 1~n 的连续整数
void fillArr(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        arr[i] = i + 1;
    }
}

int main() {
    int res[5]; // 空数组
    fillArr(res, 5);
    printArr(res, 5); // 输出:1 2 3 4 5
    return 0;
}

三、常见坑点与避坑指南

  1. 坑点 1:硬编码数组长度错误写法(固定长度 5,适配性差):

    c

    运行

    void printArr(int arr[]) {
        for (int i = 0; i < 5; i++) { // 硬编码,数组长度≠5时会越界
            printf("%d ", arr[i]);
        }
    }
    

    避坑:必须显式传递数组长度。

  2. 坑点 2:在函数内计算数组长度错误写法(sizeof 计算的是指针大小):

    c

    运行

    void printArr(int arr[]) {
        int len = sizeof(arr) / sizeof(int); // 错误!arr是指针,len=1(32位)/2(64位)
        for (int i = 0; i < len; i++) {
            printf("%d ", arr[i]);
        }
    }
    

    避坑:仅能在数组定义的作用域(如 main)中用 sizeof 计算长度。

  3. 坑点 3:返回局部数组的指针错误写法(局部数组出函数后销毁,指针失效):

    c

    运行

    int* createArr() {
        int arr[5] = {1,2,3,4,5}; // 局部数组,栈内存
        return arr; // 错误!返回野指针
    }
    

    避坑:改用动态数组(malloc)或传入外部数组。

四、经典应用场景

  1. 数组排序:函数接收数组 + 长度,实现冒泡 / 选择排序;
  2. 数组查找:函数接收数组 + 长度 + 目标值,返回目标值下标;
  3. 数组求和 / 平均值:函数接收数组 + 长度,返回计算结果。

示例(数组求和):

c

运行

int sumArr(int arr[], int len) {
    int sum = 0;
    for (int i = 0; i < len; i++) {
        sum += arr[i];
    }
    return sum;
}

int main() {
    int arr[] = {1,2,3,4,5};
    int len = sizeof(arr)/sizeof(int);
    printf("数组和:%d\n", sumArr(arr, len)); // 输出:15
    return 0;
}

总结

C 语言中函数操作数组的核心是:

  1. 数组传参退化为指针,必须传长度;
  2. 函数可直接修改原数组(指针特性);
  3. 避免返回局部数组指针,优先传入外部数组
#include<stdio.h>

void printArr(int arr[], int n){
    for(int i=0;i<n;i++){
        printf("%d\n", arr[i]);
    }
}

int main(){
    // int 类型的数组
    int arr1[]={1,2,3,4,5,8,9};
    // 计算数组的元素个数:用数组的整体大小/单个元素大小
    int n_arr1= sizeof(arr1)/sizeof(int);
    printf("%d\n",n_arr1);

    printArr(arr1, n_arr1);
    int arr2[]={7,8,9};
    printArr(arr2,3);
}

image.png

#include<stdio.h>
//数组和
int getArrSum(int arr[], int len) {
    int sum = 0;
    for (int i = 0; i < len; i++) {
        sum += arr[i];
    }
    return sum;
}
// 任务2:求数组最大值
int getArrMax(int arr[], int len) {
    int max = arr[0]; 
    for (int i = 1; i < len; i++) {
        if (arr[i] > max) {
            max = arr[i]; 
        }
    }
    return max;
}
// 任务3:查找数组元素,返回下标(找不到返回-1)
int findArrValue(int arr[],int len,int val){
	 for (int i = 0; i < len; i++) {
        if (arr[i] == val) {
            return i;
        }
}
}
int main() {
    int arr[3] = {1,2,3};
    printf("%d\n", getArrSum(arr, 3));
    printf("数组最大值:%d\n", getArrMax(arr, 3));
    printf("元素2的下标:%d\n", findArrValue(arr, 3, 2));
}

运行结果如下:

image.png