【问题标题】:Why does sizeof(intArray)/sizeof(int) give different values? [duplicate]为什么 sizeof(intArray)/sizeof(int) 给出不同的值? [复制]
【发布时间】:2011-04-02 15:00:54
【问题描述】:

可能的重复:
C++: sizeof for array length
Sizeof array passed as parameter

#include "stdafx.h"
#include <iostream>

using namespace std;

void PrintArrayLength(int arr[])
{
    cout << "Function Array length is: " << sizeof(arr)/sizeof(int) << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    int arr[] = {1, 2, 3};

    cout << "Array length is: " << sizeof(arr)/sizeof(int) << endl; // print 3

    PrintArrayLength(arr); // print 1
    return 0;
}

为什么一个地方 sizeof(arr)/sizeof(int) 的值为 1,而另一个地方的值为 3?

【问题讨论】:

  • SO 上已经有很多重复项,例如Sizeof array passed as parameter
  • @PaulR:虽然确实有很多重复,但这不是其中之一。这个问题是关于指向动态分配的内存块的指针,而这个问题是关于按值传递数组的衰减指针行为。答案相同,但问题不同。
  • @Tomalak:你确定我们在看同一个问题吗?在最初得到一个糟糕的示例重复后,我确实更新了我的评论,但我认为 Sizeof array passed as parameter 肯定是一个有效的重复。无论哪种方式,都有很多可供选择。
  • @PaulR:我在看你的预编辑评论。

标签: c++


【解决方案1】:

因为当您将数组按值传递给函数时,您实际上是在传递一个指针(指向数组的第一个元素)。

void PrintArrayLength(int arr[])
{
    cout << "Function Array length is: " << sizeof(arr)/sizeof(int) << endl;
}

其实

void PrintArrayLength(int* arr)
{
    cout << "Function Array length is: " << sizeof(arr)/sizeof(int) << endl;
}

不要被允许您将数组声明为int[] 的语法糖误导。实际上,没有这种类型,而您真正写的是:

int arr[3] = {1, 2, 3};

只是编译器可以从初始化程序中为您简单地填写3


顺便说一句,如果您通过引用传递数组,您可以保留尺寸。为方便起见,您可以使用模板,这样无论数组具有什么维度(因为维度是类型的一部分),您都只需要一个函数:

template <size_t N>
void PrintArrayLength(int (&arr)[N])
{
    cout << "Function Array length is: " << sizeof(arr)/sizeof(int) << endl;
}

对此的扩展建议不要使用sizeof。你很容易掉进你掉进的陷阱,以为你正在评估一个数组,而实际上,你不是。改用这个:

template <typename T, size_t N>
size_t length_of_array(T (&)[N]) {
   return N;
}

尝试在除正确数组之外的任何对象上使用此函数将失败并出现编译器错误,而不是像您的代码那样默默地给出误导性值。

当然,用boost::array(或C++0x 中的std::array)甚至std::vector(可以调整大小)类型的对象替换您对原始数组的使用是最好的方法。 :)

【讨论】:

  • ...指针的大小通常是int 的大小,或者两倍,所以你很可能一直得到 1 或 2(取决于平台)。
  • @Tomalak,这就是我的猜测。 ——谢谢
  • 不错的模板建议,谢谢(我不知道常量模板参数也会被引入!)
  • @sehe:你的意思是“推断”? :)
  • 诱导、推导、推断、检测、模式匹配、填充、识别、解决 :) 推导,那里,是的,谢谢
【解决方案2】:

Tomalak Geret'kal 是对的。

对于你想要的功能,你可以使用这个:

void DoSomethingWithArray(int* arr, size_t n)
{
    cout << "Function Array length is: " << n << endl;
}

template< size_t n >
inline void DoSomethingWithArray(int (&arr)[n])
{
    // n == sizeof(arr)/sizeof(int)
    DoSomethingWithArray( arr, n );
}

我正在使用函数void DoSomethingWithArray(int* arr, size_t n),而不是直接在函数模板的主体内编写代码,因为如果函数的主体足够大,为每个函数实例化单独的函数(专门从函数模板)将浪费资源pogram 中曾经使用过的数组 n 的大小。

【讨论】:

  • 这是一个平衡。额外的代码可能不会比一个全新的堆栈框架更糟糕。取决于用例。
  • @Tomalak Geret'kal:当然,我不认为创建额外的堆栈帧是一个好的选择。我显然依赖于直接内联单个函数调用,而不是根据数组大小值实例化一个函数——如果打开优化,理智的编译器总是会这样做。即使没有优化,通过单个调用或任何其他小动作(每 n 值)实例化小函数也是可以的,但如果函数很大,那就不能接受了。
  • 好点;我忘记了!
猜你喜欢
  • 2012-06-14
  • 2021-05-12
  • 2013-09-24
  • 2021-12-17
  • 2014-08-19
  • 1970-01-01
  • 2012-05-29
  • 2017-03-26
  • 2014-05-25
相关资源
最近更新 更多