【问题标题】:How do you get the size of array that is passed into the function?你如何获得传递给函数的数组的大小?
【发布时间】:2011-04-21 14:28:34
【问题描述】:

我正在尝试编写一个打印出数组中元素的函数。但是,当我使用传递的数组时,我不知道如何迭代数组。

void
print_array(int* b)
{
  int sizeof_b = sizeof(b) / sizeof(b[0]);
  int i;
  for (i = 0; i < sizeof_b; i++)
    {
      printf("%d", b[i]);
    }
}

对传递的数组进行迭代的最佳方法是什么?

【问题讨论】:

  • 问题不应同时标记为 C 和 C++。它们是不同的语言,正确答案因您想要的语言而异。
  • finding size of int array的可能重复

标签: c arrays


【解决方案1】:

您还需要将数组的大小传递给函数。
当您将数组传递给您的函数时,您实际上是在传递该数组中第一个元素的地址。所以指针只指向函数内部的第一个元素。

由于数组中的内存是连续的,您仍然可以使用指针算法,例如 (b+1) 指向第二个元素或等效的 b[1]

void print_array(int* b, int num_elements)
{
  for (int i = 0; i < num_elements; i++)
    {
      printf("%d", b[i]);
    }
}

这个技巧只适用于数组而不是指针:

sizeof(b) / sizeof(b[0])

...和arrays are not the same as pointers.

【讨论】:

  • +1,但对于数组大小,您应该使用size_t,而不是int
  • 我几乎做到了,但我不确定这是否是 C 中的一种类型,我试图提供一个适用于两者的答案,因为问题被标记为两者。
  • 我尝试了与您在该答案中提供的链接相同的解释:stackoverflow.com/questions/3613302/… 确实是非常常见的错误。
【解决方案2】:

你为什么不为此使用函数模板(C++)?

template<class T, int N> void f(T (&r)[N]){
}

int main(){
    int buf[10];
    f(buf);
}

编辑 2:

qn 现在似乎有 C 标记,而 C++ 标记已被删除。

【讨论】:

  • 我认为更好的问题是为什么不使用矢量?
  • @JoshD: 没有 C++0x,固定大小的数组非常方便,您可以用它来初始化它们(ala int a[] = { 1, 2, 3};。它们还避免了堆分配 - 如果它们特别好'是小,transcient,并且在一个性能敏感的循环中。
  • 这是一个聪明的解决方案,但它只适用于静态大小的数组。
  • @Tony:我同意。但在这种情况下,您可以使用sizeof(b) / sizeof(b[0]) 技巧并将大小传递给函数,对吗?我的印象是这些是指向动态大小的数组的指针。可能我理解错了。
  • @Greg/@JoshD:检查问题:抱怨是 int sizeof_b = sizeof(b) / sizeof(b[0]); 无法在被调用函数内完成。显然,尝试使用它表明编译时常量大小。
【解决方案3】:

你可以试试这个……

#include <cstdio>                                                               

void 
print_array(int b[], size_t N) 
{ 
    for (int i = 0; i < N; ++i) 
        printf("%d ", b[i]);
    printf("\n");
}

template <size_t N>
inline void 
print_array(int (&b)[N]) 
{
    // could have loop here, but inline forwarding to
    // single function eliminates code bloat...
    print_array(b, N);
}                                                                                

int main()                                                                      
{                                                                               
    int a[] = { 1, 2 };                                                         
    int b[] = { };
    int c[] = { 1, 2, 3, 4, 5 };                                                

    print_array(a);                                                             
    // print_array(b);                                                          
    print_array(c);                                                             
}

...有趣的是 b 不起作用...

array_size.cc: In function `int main()':
array_size.cc:19: error: no matching function for call to `print_array(int[0u])'

JoshD 在 cmets 下面的问题中指出了 re 0 大小的数组(GCC 扩展),以及上面的大小推断。

【讨论】:

  • @Tony: b 不起作用,因为它的大小为 1 但有 0 个元素。
  • 为 3 个不同大小的数组创建 3 个函数有点过分,不是吗?最好有一个通用打印函数,并让模板函数(内联?)使用数组和大小参数调用通用函数,不是吗?
  • @Jonathan 和@Tony:即使使用前端,您也会为每个 N 值获得一个新类型。这是一些严重的代码膨胀。既然可以有函数参数,为什么还要使用模板?
  • @JoshD:一种新类型?不,你不会,因为没有虚函数,RTTI 不会涵盖它:因此成本为零。无论如何,大小检测包装器都会被标记为内联,编译器将生成与程序员传递大小完全相同的代码,但在调用站点不可能有类型。
  • @Josh:新类型?新模板功能,是的,但不是新类型,确定吗?如果它是内联定义的(template &lt;size_t N&gt; void print_array(int (&amp;b([N]) { print_array(b, N); }),膨胀是最小的,甚至不存在,不是吗。由于我主要是一名 C 程序员,尽管有徽章,我会使用该函数并期望使用显式参数调用它 - 正如您所建议的那样。
【解决方案4】:

对于 C,您必须传递数组的长度(元素数量)。

对于 C++,您可以传递长度,但是,如果您可以访问 C++0x,最好使用std::array。请参阅 herehere。它携带长度,并在您使用at() 成员函数访问元素时提供越界检查。

【讨论】:

    【解决方案5】:

    C99中,你可以要求一个数组一个数组至少有n个元素,因此:

    void print_array(int b[static n]);
    

    6.7.5.3.7: 将参数声明为“类型数组”应调整为“限定指针 type'',其中类型限定符(如果有)是在 [ 和 ] 中指定的那些 数组类型推导。如果关键字 static 也出现在 数组类型推导,然后对函数的每次调用,对应的值 实际参数应提供对数组的第一个元素的访问,其中至少有 由大小表达式指定的元素。

    在 GCC 中,您可以像这样 pass the size of an array implicitly

    void print_array(int n, int b[n]);
    

    【讨论】:

    • 值得一提的是,T foo(T myptr[static 1]) 是一种方便且可移植的方式来表达foo 采用类型为T * 的指针,该指针不能是NULL(或任何其他无效的指针值)比如(T *)-1)。
    • 而且我相信您给出的void print_array(int n, int b[n]); 示例是标准C,而不是gcc 扩展。但是,对于一维数组,它完全没用。当它变得有用时,当您在第一个维度之外的维度中拥有可变大小的多维数组时。
    【解决方案6】:

    在 c++ 中,您还可以使用某种类型的列表类,该类实现为具有 size 方法的数组或具有 size 成员的结构(在 c 或 c++ 中)。

    【讨论】:

      【解决方案7】:

      使用变量传递数组的大小。 int sizeof_b = sizeof(b) / sizeof(b[0]); 除了获取预先声明的数组大小之外什么都不做,这是已知的,您可以将它作为参数传递;例如,void print_array(int*b, int size)size 也可以是用户定义的大小。

      int sizeof_b = sizeof(b) / sizeof(b[0]);在元素个数小于预先声明的array-size时会引起冗余迭代。

      【讨论】:

        【解决方案8】:

        这个问题已经有一些很好的答案,例如the second one。但是缺乏解释,所以我想扩展示例并解释它:

        使用模板和模板参数,在这种情况下None-Type Template parameters 可以获取任何类型的固定数组的大小。

        假设你有这样一个函数模板:

        template<typename T, int S>
        int getSizeOfArray(T (&arr)[S]) {
            return S;
        }
        

        模板显然适用于任何类型(此处为 T)和固定整数(S)。 如您所见,该函数需要对类型为 T 的 S 对象数组的引用,正如您所知道的,在 C++ 中,您不能通过值而是通过引用将数组传递给函数,因此函数必须进行引用。

        现在如果你像这样使用它:

        int i_arr[] = { 3, 8, 90, -1 };
        std::cout << "number f elements in Array: " << getSizeOfArray(i_arr) << std::endl;
        

        编译器会隐式实例化模板函数并检测参数,所以这里的 S 是4,它被返回并打印到输出。

        【讨论】:

          猜你喜欢
          • 2018-04-25
          • 1970-01-01
          • 2015-12-07
          • 1970-01-01
          • 1970-01-01
          • 2011-03-04
          • 2014-10-27
          • 1970-01-01
          • 2011-10-19
          相关资源
          最近更新 更多