数组长度

在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
      }
      
11-24 12:07