函数形参传数组

一、数组形式的参数会被编译器自动调整为指针

在 C/C++ 函数参数中,数组形式的参数会被编译器自动调整为指针 。

所以:

c

复制代码
void Fun(int num[6])

等价于:

c

复制代码
void Fun(int *num)

具体说明:

  1. 数组大小 6 不起作用

    编译器忽略 6,不会检查传入的数组是否真的至少有 6 个元素。

  2. 传递的是指针

    调用 Fun(arr) 时,传递的是数组首元素的地址,不会拷贝整个数组。

  3. 常见写法

    为了表达语义,有时仍会写 int num[6] 提示预期数组大小,但实际参数类型仍是 int*。

  4. 验证方法

    c

    复制代码
    void Fun(int num[6]) {
        printf("%zu\n", sizeof(num)); // 输出指针大小(如 8 字节),不是 6*4
    }

例外情况

只有在函数参数 中才会这样。

如果是 int num[6] 作为局部变量,那么 sizeof(num) 就是整个数组的大小。

二、为什么等价

等价的根本原因是:为了效率和避免不必要的数组拷贝。

具体来说,有以下几个关键点:

1. 值传递的代价问题

在 C/C++ 中,函数参数默认是值传递。这意味着,如果你真的把整个数组传给函数,就需要拷贝数组中的每一个元素。

  • 如果数组很大(比如 int num[10000]),每次调用函数都要拷贝 10000 个 int,内存和时间开销会非常大。

  • 为了解决这个问题,C 语言的设计者决定:永远不直接传递数组本身。

2. 数组名会"退化"为指针

在绝大多数表达式中,数组名会被隐式地转换为指向其首元素的指针。这个行为叫做 "数组退化"。

例如:

c

复制代码
int arr[6] = {1,2,3,4,5,6};
int *p = arr;  // arr 退化成 &arr[0]

当你在函数参数中写 int num[6] 时,编译器会自动将它重写 为 int *num。

C++ 继承了这一规则,为了兼容 C 语言。

3. 标准文档明确规定

C 标准(如 C99 §6.7.6.3)明确指出:

声明函数参数为"类型 数组名大小"时,它会被调整为"类型 * 数组名"。

所以:

  • void Fun(int num[6]) → 编译器看到 int num[6] 作为参数 → 调整成 int *num

  • 调用时 Fun(arr) → arr 退化为 &arr[0] → 传给 num 的是指针(地址)

最终效果:函数内部操作 num[i],其实是通过指针 + 偏移量访问原始数组的元素。

4. 如果不等价会怎样?

如果数组参数真的是按值传递整个数组:

  • 每次函数调用都会拷贝整个数组,效率极低。

  • 无法通过函数修改原数组的内容(因为操作的是拷贝)。

  • 但这正是 C 语言缺乏引用传递 (C++ 有引用)时的折中方案:传指针即可修改原数组。

5. 验证示例

c

复制代码
#include <stdio.h>

void Fun(int num[6]) {
    printf("sizeof(num) = %zu\n", sizeof(num));   // 输出 8(64位系统)或 4(32位系统)
    printf("sizeof(int*) = %zu\n", sizeof(int*)); // 和上面一样
    num[0] = 100;  // 修改的是原数组
}

int main() {
    int arr[6] = {0};
    printf("sizeof(arr) = %zu\n", sizeof(arr));   // 输出 24 (6 * 4)
    Fun(arr);
    printf("arr[0] = %d\n", arr[0]);              // 输出 100,说明修改了原数组
    return 0;
}

输出:

text

复制代码
sizeof(arr) = 24
sizeof(num) = 8
sizeof(int*) = 8
arr[0] = 100

可以看到:

  • 函数内部的 sizeof(num) 是指针大小,不是数组大小。

  • 修改 num[0] 会影响外部的 arr[0]。

总结

等价的原因:

  1. 设计选择:避免数组拷贝,提高效率。

  2. 自动退化:数组参数被编译器自动调整为指针。

  3. 语义统一 :无论你写 int num[6]、int num[] 还是 int *num,最终参数类型都是 int*。

所以,写 int num[6] 只是语法糖,主要作用是给代码阅读者一个提示:"这个函数期望传入一个至少有 6 个元素的数组",但编译器并不检查这个约束。

相关推荐
2601_960356385 分钟前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah29 分钟前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO932 分钟前
指针的算术运算详解
java·数据结构·算法
sunshine22 girl33 分钟前
Java学习六 Java常见API-2--String-3-字符串的截取替换和其他方法
java·开发语言·学习
Coder-magician37 分钟前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
EatFan1 小时前
从“框架混战“到“运行时收敛“:2026 年 AI Agent 开发框架的三条路线之争
java·数据库·人工智能·多智能体·ai agent·mcp·agent 框架
垆边人似月.1 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
小蒜学长1 小时前
基于SpringBoot的佳新超市管理系统设计与实现系统(代码+数据库+LW)
java·数据库·spring boot·后端·佳新超市管理系统
sunshine22 girl1 小时前
Java学习六 Java常见API-1-Radom随机数
java·开发语言·学习
潼心1412o2 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法