导读:本期聚焦于小伙伴创作的《C++中数组作为函数参数怎么传递 数组退化与指针参数解析》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++中数组作为函数参数怎么传递 数组退化与指针参数解析》有用,将其分享出去将是对创作者最好的鼓励。

在C++编程中,数组作为函数参数传递是日常开发中非常常见的操作,但很多初学者甚至有一定经验的开发者,都对数组传递时的退化现象和指针参数的关联逻辑存在疑惑,本文将深入解析相关机制。

C++中数组作为函数参数怎么传递 数组退化与指针参数解析

C++数组作为函数参数的常见传递方式

1. 以数组形式声明参数

这种写法看起来是传递了完整的数组,但实际上只是语法糖,编译器会自动将其处理为指针形式。

#include <iostream>
using namespace std;

// 参数看似是数组,实际会被解析为指针
void print_array(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int nums[5] = {1, 2, 3, 4, 5};
    print_array(nums, 5);
    return 0;
}

2. 以指针形式声明参数

这种方式直接声明参数为指针,和第一种写法在编译后的效果完全一致,是更直观的写法。

#include <iostream>
using namespace std;

// 直接声明为指针参数,和数组形式声明效果相同
void print_array_ptr(int* arr, int len) {
    for (int i = 0; i < len; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int nums[5] = {1, 2, 3, 4, 5};
    print_array_ptr(nums, 5);
    return 0;
}

3. 传递数组的引用

如果希望避免数组退化,可以传递数组的引用,这种方式需要明确指定数组的长度。

#include <iostream>
using namespace std;

// 传递数组的引用,必须指定数组长度
void print_array_ref(int (&arr)[5]) {
    for (int i = 0; i < 5; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

int main() {
    int nums[5] = {1, 2, 3, 4, 5};
    print_array_ref(nums);
    // 以下调用会编译报错,因为数组长度不匹配
    // int nums2[3] = {1,2,3};
    // print_array_ref(nums2);
    return 0;
}

数组退化的本质原因

数组退化指的是当数组作为函数参数传递,或者参与表达式运算时,会自动转换为指向数组首元素的指针,丢失数组的长度信息。这个现象的原因是C++为了兼容C语言的特性,同时避免传递大数组时产生大量的内存拷贝开销,所以设计了数组到指针的隐式转换规则。

当数组名出现在表达式(除了作为<sizeof>操作符的操作数、作为取地址符<&>的操作数、作为字符串字面量初始化字符数组的场景)中时,数组名会被自动转换为指向首元素的指针。比如下面的代码可以验证这个特性:

#include <iostream>
using namespace std;

int main() {
    int nums[5] = {1,2,3,4,5};
    // sizeof作用于数组名时,得到的是整个数组的大小
    cout << "数组总大小: " << sizeof(nums) << endl; // 输出20(假设int为4字节)
    // 数组名参与赋值表达式,退化为指针
    int* p = nums;
    cout << "指针大小: " << sizeof(p) << endl; // 输出8(64位系统指针大小)
    // 数组作为函数参数传递时,sizeof得到的是指针大小
    return 0;
}

数组参数和指针参数的区别与联系

很多人会疑惑函数参数声明为int arr[]int* arr有什么区别,实际上在C++的函数参数声明中,这两种写法是完全等价的,编译器会将前者自动调整为后者。我们可以通过下面的代码验证:

#include <iostream>
using namespace std;

// 以下两个函数声明是等价的,无法同时存在于同一个作用域
// void func(int arr[]);
// void func(int* arr);

void func(int arr[]) {
    cout << "arr是指针,大小: " << sizeof(arr) << endl;
}

int main() {
    int nums[5] = {1,2,3,4,5};
    func(nums);
    return 0;
}

两者的核心差异仅存在于声明层面,实际编译后的函数签名完全一致。如果需要区分参数到底是数组还是指针,只能通过传递引用的方式,因为数组引用和指针是完全不同的类型。

不同传递方式的适用场景

  • 如果不需要知道数组的长度,只需要遍历数组元素,使用指针参数或者数组形式的参数即可,同时额外传递长度参数。
  • 如果需要保证数组的长度固定,避免传入错误长度的数组,可以使用数组引用的方式传递参数,在编译阶段就检查数组长度是否匹配。
  • 如果需要修改原数组的内容,以上三种方式都可以实现,因为传递的都是数组首元素的地址,修改元素会影响原数组。如果不需要修改数组内容,可以在参数前加<const>修饰,比如void func(const int* arr, int len)
注意:不要试图在函数内部通过sizeof(arr)/sizeof(arr[0])的方式计算数组长度,因为此时arr已经退化为指针,这个计算得到的只是指针大小和元素大小的比值,和数组实际长度无关。

C++数组传递数组退化指针参数函数参数修改时间:2026-06-15 21:30:44

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。