函数形参传数组

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

在 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 个元素的数组",但编译器并不检查这个约束。

相关推荐
极客天成ScaleFlash2 小时前
极客天成 NVFile 存算融合解决方案
算法·数据挖掘
一只幸运猫.2 小时前
字节跳动Java大厂面试版
java·开发语言·面试
2301_813599552 小时前
如何监控表空间自动扩展_DBA_DATA_FILES中的MAXBYTES分析
jvm·数据库·python
xier_ran2 小时前
【C++】“内部”、“外部”、“派生类”、“友元“类
java·开发语言·c++
Reisentyan2 小时前
[杭电春季联赛5]1004 赛马
算法
m0_716430072 小时前
mysql数据库表名区分大小写吗_通过lower case table names配置
jvm·数据库·python
雨墨✘2 小时前
基于比较的三种排序算法:插入排序、合并排序和快排序
数据结构·算法·排序算法
故事和你912 小时前
洛谷-数据结构1-2-二叉树1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
凭君语未可2 小时前
从静态代理走向动态代理:理解 JDK 动态代理的本质
java·开发语言