C 语言 | 在函数中操作数组

1. 引言

在 C 语言中,数组以特殊的方式传递给函数。当你将数组传递给函数时,实际传递的是指向其第一个元素的指针。这意味着函数操作的是原始数组,而不是副本。理解这一行为对于编写高效且正确的 C 程序至关重要。

2. 数组如何传递给函数

当你编写一个接受数组作为参数的函数时,编译器会将参数视为指针。例如,以下两个函数声明是等价的:

c 复制代码
void print_array(int arr[], int size);
void print_array(int *arr, int size);

两者都告诉编译器 arr 指向一个整数数组的第一个元素。由于数组是通过引用(即指针)传递的,函数内部所做的任何修改都会影响调用者中的原始数组。

3. 将数组传递给函数

要将数组传递给函数,只需使用不带方括号的数组名。数组名会退化为指向其第一个元素的指针。

c 复制代码
#include <stdio.h>

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

int main() {
    int numbers[] = {10, 20, 30, 40, 50};
    int n = sizeof(numbers) / sizeof(numbers[0]);

    print_array(numbers, n);
    return 0;
}

输出:

复制代码
10 20 30 40 50

注意,在 main 函数中,sizeof(numbers) 给出的是数组的总字节数,因此除以 sizeof(numbers[0]) 可以得到元素的个数。然而,在函数内部,sizeof(arr) 只会给出指针的大小,而不是整个数组的大小。这就是为什么必须显式传递数组大小的原因。

4. 在函数内部修改数组

由于数组是通过引用传递的,你可以在函数内部直接修改原始数组,而无需返回任何内容。

c 复制代码
#include <stdio.h>

void double_values(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int n = sizeof(numbers) / sizeof(numbers[0]);

    double_values(numbers, n);

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

输出:

复制代码
2 4 6 8 10

函数 double_values 直接修改了 numbers 的元素,这些修改在调用返回后于 main 函数中仍然可见。

5. 使用指针运算

由于数组参数实际上是一个指针,你可以在函数内部使用指针运算来遍历数组。

c 复制代码
#include <stdio.h>

int sum_array(int *arr, int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += *(arr + i);
    }
    return total;
}

int main() {
    int numbers[] = {5, 10, 15, 20};
    int n = sizeof(numbers) / sizeof(numbers[0]);

    int result = sum_array(numbers, n);
    printf("Sum: %d\n", result);
    return 0;
}

输出:

复制代码
Sum: 50

在这里,*(arr + i) 等价于 arr[i]。两种形式访问的是同一个元素。

6. 二维数组

传递二维数组时需要指定第二维的大小,因为编译器需要知道每一行有多少列,才能正确计算地址。

c 复制代码
#include <stdio.h>

void print_matrix(int matrix[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int grid[][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    print_matrix(grid, 3);
    return 0;
}

输出:

复制代码
1 2 3
4 5 6
7 8 9

参数 int matrix[][3] 表示一个指向包含 3 个整数的数组的指针。第一个维度可以省略,但第二个维度必须存在。

7. 常见陷阱

  • 忘记传递数组大小 :在函数内部,sizeof(arr) 返回的是指针的大小,而不是数组的大小。务必显式传递元素的个数。
  • 在只需要读取时却进行了修改 :如果函数不应修改数组,应将参数声明为 const int arr[],以防止意外修改。
  • 误以为数组会被复制:数组在传递给函数时永远不会被复制。如果需要副本,请在函数内部手动创建。

8. 总结

  • 数组作为指向其第一个元素的指针传递给函数。
  • 函数内部的修改会影响原始数组。
  • 始终单独传递数组的大小。
  • 使用 const 保护只读数组。
  • 对于多维数组,除第一维外,必须指定所有维度。

掌握在函数中操作数组是编写简洁高效 C 代码的关键一步。

相关推荐
怕浪猫6 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
朝朝辞暮i7 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
Evand J8 小时前
【MATLAB例程】三维RRT+APF避障路径规划与到达角(AOA)定位算法|三维路径优化与定位仿真例程
算法·matlab·路径规划·代码·定位·rrt·aoa
小师兄吃牛肉8 小时前
C语言篇:宏
c语言·开发语言
郑同学的笔记8 小时前
【c++随笔28】strcmp 和 memcmp对比
开发语言·c++
随意起个昵称8 小时前
【背包dp】输出方案路径
c++·动态规划
炸膛坦客8 小时前
单片机开发工具篇:(十四)配置输出 .map 文件及其本地路径
c语言·单片机·嵌入式硬件
weixin_307779139 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
kakakahahahaha9 小时前
Windows C盘临时文件清理:%temp%、Windows Temp、Prefetch、Windows.old与hiberfil.sys处理指南
c语言·开发语言·windows