当前位置: 首页 > article >正文

C++ 中数组作为参数传递时,在函数中使用sizeof 为什么无法得到数组的长度

数组长度

在C++ 中并没有提供java,C#的size,length的数组长度。

int arr[10];
std::cout << sizeof(arr)/ sizeof(int) << std::endl; 

数组作为参数传递

#include "iostream"
using namespace std;

int main() {
    int arr[]={1,2,3,4,5};
    cout<<sizeof(arr)/sizeof(int)<<endl;  //输入的是 5
    return 0;
}

定义一个函数

#include "iostream"
using namespace std;

int multiply(int arr[],int number){
    cout<<sizeof(arr)/sizeof(int)<<endl;  //输出的 是2
}

int main() {
    int arr[]={1,2,3,4,5};
    cout<<sizeof(arr)/sizeof(int)<<endl; //输入的是 5
    multiply(arr,3);
    return 0;
}

这时候在函数中 计算出来的长度 并不是数组真实的长度;
在 C++ 中,当数组作为函数参数传递时,sizeof 无法得到数组的长度的原因是数组会退化(decay)为指针。具体来说,数组名在作为参数传递时,编译器会将数组的地址(即指向数组第一个元素的指针)传递给函数,而不是整个数组本身。


分析

  1. 数组在参数传递中的退化
    在函数参数中,int arr[]int arr[10] 实际上被编译器解释为 int* arr,这意味着在函数中访问 arr 时,它只是一个指向数组首元素的指针,而不再是一个完整的数组。

    • 原数组的大小信息并不会被传递到函数中。
    • sizeof(arr) 的结果是指针本身的大小,而不是数组的大小。

    例如:

    void foo(int arr[]) {
        std::cout << sizeof(arr) << std::endl; // 输出指针的大小,例如 8(在 64 位系统上)
    }
    
    int main() {
        int arr[10];
        foo(arr);
    }
    

    在函数 foo 中,arr 是一个指针,不再是 main 中的数组。因此 sizeof(arr) 是指针大小。

  2. 函数参数声明的等价性
    函数参数中声明 int arr[]int* arr 是等价的,这就明确了传递到函数的是一个指针,而不是整个数组。

    例如:

    void foo(int arr[]);  // 等价于
    void foo(int* arr);
    
  3. 数组本质与内存模型

    • 静态数组在内存中是连续存储的,编译器在数组作用域内可以推导其大小,因此 sizeof 可以计算静态数组的总大小。
    • 但是当数组退化为指针后,指针只存储了数组首地址,无法通过这个地址直接推断数组的大小。
    • 这与动态分配数组类似:动态分配的数组通过指针访问,也没有内置的大小信息。
  4. 如何在函数中获取数组大小?
    如果确实需要在函数中知道数组的大小,可以采用以下方法:

    • 显式传递数组大小
      void foo(int arr[], size_t size) {
          std::cout << "Array size: " << size << std::endl;
      }
      
      int main() {
          int arr[10];
          foo(arr, sizeof(arr) / sizeof(arr[0]));
      }
      
    • 使用模板(适用于静态数组):
      模板可以捕获数组的大小信息:
      template <size_t N>
      void foo(int (&arr)[N]) {
          std::cout << "Array size: " << N << std::endl;
      }
      
      int main() {
          int arr[10];
          foo(arr); // 输出 10
      }
      

http://www.kler.cn/a/408117.html

相关文章:

  • Linux设置以及软件的安装(hadoop集群安装02)
  • 学习python的第十三天之函数——函数的返回值
  • SpringBoot 集成 html2Pdf
  • 跨境出海安全:如何防止PayPal账户被风控?
  • 全面提升系统安全:禁用不必要服务、更新安全补丁、配置防火墙规则的实战指南
  • RabbitMQ简单应用
  • 【MATLAB源码-第222期】基于matlab的改进蚁群算法三维栅格地图路径规划,加入精英蚁群策略。包括起点终点,障碍物,着火点,楼梯。
  • Linux探秘坊-------1.系统核心的低语:基础指令的奥秘解析(1)
  • VSCode 使用技巧
  • Java开发经验——并发工具类库线程安全问题
  • IP转发流程
  • Elasticsearch搜索流程及原理详解
  • Java Web后端项目的特点和组成部分
  • 【element-tiptap】Tiptap编辑器核心概念----内容、扩展与词汇
  • 基于NVIDIA NIM 平台打造智能AI知识问答系统
  • 【JAVA 笔记】12 带有数据库文件的完整的JDBC访问例子,命令行界面
  • C++适配器模式之可插入适配器的实现模式和方法
  • 大模型(LLMs)推理篇
  • 前端开发调试之移动端调试学习笔记
  • 【自动化】如何从列表中找到图片并命名保存下来
  • 2061:【例1.2】梯形面积(http://ybt.ssoier.cn:8088/problem_show.php?pid=2061)
  • 科研实验室的数字化转型:Spring Boot系统
  • C# 命名空间详解(一)
  • 计算机网络socket编程(5)_TCP网络编程实现echo_server
  • C语言:操作符详解1
  • Java 腾讯云短信发送