函数形参传数组

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

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

相关推荐
sheeta19984 小时前
LeetCode 每日一题笔记 日期:2026.05.08 题目:3629. 素数跳跃最小次数
笔记·算法·leetcode
叼烟扛炮4 小时前
C++ 知识点08 类与对象
开发语言·c++·算法·类和对象
米粒14 小时前
力扣算法刷题 Day 63 Bellman_ford 算法
数据库·算法·leetcode
你不是我我10 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
雪碧聊技术10 小时前
大模型爆火!Java后端如何抓住Agent全栈开发的风口
java·大模型·agent·全栈开发
IT大白鼠10 小时前
AIGC性能的关键瓶颈:算力、数据、算法三者如何互相制约?
算法·aigc
白雪茫茫11 小时前
监督学习、半监督学习、无监督学习算法详解
python·学习·算法·ai
FengyunSky11 小时前
浅析 空间频率响应 SFR 计算
算法
树下水月11 小时前
PHP 一种改良版的雪花算法
算法·php·dreamweaver
逻辑驱动的ken11 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展