【问题标题】:Passing arrays as parameters in C在 C 中将数组作为参数传递
【发布时间】:2011-12-30 14:14:14
【问题描述】:

我(我想我)明白,如果数组的大小是在编译时在堆栈上声明的,则只能检索数组的大小(使用 sizeof),例如

int my_array[] = {1,2,3};
sizeof(my_array) == 3;

一旦开始使用指针,就会丢失此长度信息。

例如如果将指向 int 的指针作为函数参数传递以将 int 数组获取到函数中,则不能再以这种方式使用 sizeof(),它只会返回用于存储指针的字节数。

显然,了解数组的长度至关重要。

那么在传递数组时我应该使用以下哪个选项?

  1. 传递一个指针和一个伴随的长度参数

    int my_func(int *my_array, size_t len_my_array)

  2. 创建我自己的向量结构

    struct vector {
       int *my_array;
       size_t len;
    }
    
    int my_func(struct vector *my_vector)
    
  3. 使用别人的向量实现。 (C 是否有与 C++ 一样的默认实现?)

  4. 我错过的另一种方法?

(我目前正在使用第一个选项,但它有点笨拙,我很想知道这是否被认为是糟糕的编程习惯)

【问题讨论】:

  • sizeof(my_array) == 3; => sizeof(my_array)/sizeof(int) == 3;

标签: c arrays parameters


【解决方案1】:

您错过的一种方法是将终止元素放在数组的末尾,有点像 '\0' 标记 char* 的结尾。

这和将数组的长度作为不同的参数传递是通常的做法。

【讨论】:

  • 我可以看到决定终止元素的值应该是什么问题
  • @Hiett true,对于 char* 和其他人来说,这是可行的。你当然应该选择最适合你的情况。
【解决方案2】:

标准方法是使用第一种方法并传递一个指针和一个大小,特别是如果您希望您的代码被其他人重用。

【讨论】:

    【解决方案3】:

    在我看来,现代 C(又名 C99)中最简单的方法是使用数组表示法

    int my_func(size_t len, int my_array[len]);
    

    这与您所做的几乎相同,但首先具有大小。这样做的原因是它可以很好地扩展到多维数组

    int my_func(size_t n, size_t m, int my_array[n][m]);
    

    然后您就可以在函数内正确地计算索引,而不会遇到任何额外的困难。

    您必须确保的唯一事项

    • 列表中的大小在数组之前,因此在声明数组时大小是已知的
    • 在原型中使用与您之后用于定义的声明完全相同的声明(维度等符号等),否则您会混淆您的用户

    【讨论】:

    • 这看起来很整洁,但第二个 len(my_array[len])真的在做什么吗?例如这些都是等价的:int my_array[len]int my_array[]int *my_array
    • 不,在第一个示例中,这只是语法糖,但我觉得很好地记录了期望。第二,这真的改变了事情。否则您将无法执行 my_array[i][j] 之类的操作
    • 我注意到您建议的语法在 C99 中有效,但在 C90 中无效。
    • @Rob,对,我往往会忘记,周围仍然有古代文本的业余爱好者。我会补充的。
    • 那么将数组参数声明为 int my_array[len] 会使 sizeof my_array 正确返回数组大小?
    【解决方案4】:

    没有被广泛接受的答案,这意味着您可以依赖的唯一方法是第一种。特别是,除非您自己编写所有代码(即,从不使用任何库),否则您几乎可以指望您自己定义的任何vector 结构将不同于其他任何人使用的任何结构,所以在代码库之间的“边界”处,无论如何你都需要你的第一个方法。他们可能有自己的vector 类型供他们在内部使用。您可能有自己的一个在内部使用——但是当两者相互通信时,他们必须将该类型“解包”到其单独的组件中。

    【讨论】:

      【解决方案5】:

      这有点过头了,但我刚刚阅读了有关数组和指针的内容,您可以考虑使用 sizeof 来确定总字节数,然后除以数组包含的该数据类型的字节大小以给出你的数组长度...

      【讨论】:

      • 是的 - 我已经看到了定义的宏,但我不清楚它会在什么情况下工作 - 因为指向 int 的指针不知道有多少字节长数组是它指向
      • 实际上,仔细想想,你一定是对的——指针必须始终知道它指向的字节数,否则 free() 还能如何工作?它只接受参数,指针的名称,并设法释放堆上正确数量的内存......
      • 所以应该这样做 - #define sizearray(a) (sizeof(a) / sizeof((a)[0]))
      • 这不行,sizeof 在数组参数上返回指针类型的大小。 @bph 指针从不存储大小信息。大多数操作系统在内部存储动态分配的内存区域的大小以供free() 工作,但没有(可移植的)方法来提取它。
      猜你喜欢
      • 2017-03-19
      • 2010-10-20
      • 1970-01-01
      • 2010-10-01
      • 2013-07-24
      • 2022-01-09
      相关资源
      最近更新 更多