函数形参传数组

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

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

相关推荐
爱学习的小白柏1 小时前
【AI问数技术】多Agent协同架构:查询规划/SQL生成/洞察分析/报告生成
java·网络·人工智能·windows·sql·架构·llama
码匠许师傅1 小时前
【C++ 面试真题】30. 聊聊 C++ 的互斥锁与读写锁
java·c++·面试
沙盘客1 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享
ShineWinsu2 小时前
对于 C++:C++14中从变量模板、泛型 Lambda 到并发与字面量的解析
c++·算法
CHANCE V2 小时前
集合排序和流排序
java
土司大王2 小时前
LeetCode hot100——合并两个有序链表
算法·leetcode·链表
码行山野赴时序归途2 小时前
算法效率的度量(上):时间复杂度中的对数思维
c语言·数据结构·算法
16月6日-晴2 小时前
Java面向对象进阶—多态
java·开发语言
算AI3 小时前
基于LLM的无人机仿真测试:新方法竞赛夺佳绩
人工智能·深度学习·算法·机器学习·ai