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 代码的关键一步。

相关推荐
qz_Serene14 分钟前
练习算法题:双指针 -cpp
c++·算法·leetcode·1024程序员节
扶尔魔ocy33 分钟前
【C++开发】从裸指针到智能指针
c++·智能指针·1024程序员节
Nuanyt44 分钟前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节
碧海银沙音频科技研究院1 小时前
基于炬芯平台ATS308X多模型兼容语音识别算法
人工智能·算法·语音识别
爱读书的小胖1 小时前
LeetCode 274 H 指数 C 语言解题分析
c语言·算法·leetcode·1024程序员节
basketball6162 小时前
动态规划第一章:引论
算法·动态规划·1024程序员节
星夜离尘562 小时前
MATLAB 因果采样保持:用历史匹配和数据年龄防止未来信息泄漏
数据结构·算法·matlab
Pointer Pursuit2 小时前
Linux环境变量
linux·服务器·c语言·链表·1024程序员节
CHHH_HHH3 小时前
【Linux网络篇】初识网络与Socket编程基础
linux·服务器·c语言·开发语言·网络·后端·1024程序员节
思麟呀3 小时前
BTree的原理与 C++ 完整实现
c语言·数据结构·c++·算法·1024程序员节