函数形参传数组

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

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

相关推荐
Dillon Dong1 小时前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
ps酷教程6 小时前
Jackson 解决没有无参构造函数的反序列化问题
java
NiceCloud喜云6 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
小羊在睡觉7 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary7 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记7 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466857 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
_日拱一卒7 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
隔窗听雨眠8 小时前
Nginx网关响应慢排查手记
java·服务器·nginx
珂朵莉MM8 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法