【问题标题】:how to iterate through an array without knowing the size in c [duplicate]如何在不知道c中大小的情况下遍历数组[重复]
【发布时间】:2021-07-19 00:08:05
【问题描述】:

我有一个指向 C 中的数组的指针,我想遍历它,但我不知道大小:

int *array;

我不确定我应该如何进行。我在想我可能应该尝试通过以下方式找到大小:

int array_size = sizeof(array) / sizeof(int);

但我不知道这是否可行。我想知道是否有更优化的方法来做到这一点?

【问题讨论】:

  • 如果你只有指针,那么你就不走运了。要么必须将大小传递给函数,要么数组内容必须有一个终止符,指示数组的结束。
  • 如果您只有指针而不是原始数组定义,sizeof(array)/sizeof(int) 将不起作用。 sizeof(array) 在这种情况下是 sizeof(int *),它总是一个指针的大小。
  • 即使有一个while循环也不起作用?
  • 如果您没有大小或终止值,则循环的类型无关紧要。您如何建议在没有大小或终止值的情况下结束循环?你不能。
  • 我看不到任何人直接告诉你的最重要的事情是你所拥有的不是一个数组。这只是一个指针。一个数组在 C 中具有固定大小,用 [] 声明,这将允许您方便地迭代一个。如果没有固定大小,它就不是数组。当然,您的 array 可能指向为数组分配的一些内存,但这不会使 array 成为数组,C 编译器也是这种观点。

标签: arrays c pointers implicit-conversion sizeof


【解决方案1】:

在 C 中,无法通过指向元素的指针来判断数组中元素的数量。 sizeof(array) / sizeof(*array) 仅适用于实际数组,而不适用于指针,这是函数接收的参数,即使函数原型中使用了数组语法。在这种情况下,sizeof(array) 计算为指针的大小,因此将其除以元素的大小是没有意义的。

您的函数获取元素数量的最佳方法是将其作为单独的参数提供。

如果这不切实际,有不同的方法来推断元素的数量,依赖于调用者必须遵守的约定:

  • 数组可以有已知的固定数量的元素

  • 数组可以有一个标记值作为数组的最后一个元素。

    通常使用空指针 (NULL) 作为指针数组的标记,例如 main() 函数的 char *argv[] 参数,但请注意 int argc 也提供给它函数。

    空字节 (\0) 用于告诉 C 字符串的结尾,这是 char 的数组。

    在您的情况下,您可以考虑使用0-1 来表示数组的结尾,但是您的函数的所有调用者都必须一致地使用此约定。

【讨论】:

    【解决方案2】:

    在不知道元素数量的情况下,您无法在 c 中迭代数组。

    请注意sizeof(array) / sizeof(array[0]) 不适用于指针,即它不会给出数组中元素的数量。

    它也不会在函数内部工作,由于数组衰减到指针,数组作为参数传递。

    【讨论】:

      【解决方案3】:

      如果数组不包含已知的标记值(例如,包含字符串的字符数组的标记值是终止零字符'\0'),那么您将找不到它的结尾。

      如果你有这样的指针

      int *array;
      

      然后表达式sizeof( array ) 将产生指针本身的大小,它不依赖于指针是指向int 类型的单个对象还是指向具有已知数量的整数数组的第一个元素数组中的元素。例如,该大小可以等于48,具体取决于使用的系统。因此,表达式sizeof( array ) / sizeof( int ) 通常将始终产生12

      因此,您还必须将数组中元素的数量显式传递给函数。

      如果将指针传递给整个数组,则可以确定数组中元素的数量。例如

      void f( int( *a )[10] );
      
      //...
      
      int a[10];
      
      //...
      
      f( &a );
      

      在这种情况下,在函数中取消引用指针,您将获得一个数组类型的对象。因此表达式sizeof( *a ) 将产生原始数组的大小。

      【讨论】:

      • 我也想用指向整个数组的指针来说明这一点,但后来没有:虽然技术上正确,但它也是毫无意义的:如果你知道大小 10(你必须按顺序声明指针),您也可以像往常一样简单地将指针传递给第一个元素,然后遍历 10 个元素。指向数组的指针在 C 中也确实不惯用——由于上述原因,没有人使用它,所以人们会做双重考虑。
      • @Peter-ReinstateMonica 这与您写的不完全一样,因为可以根据泛型选择调用函数。
      • “通用选择”:不知道你的意思——你能举个例子吗?
      • @Peter-ReinstateMonica 您可以使用 _Generic 为指向数组的指针的具体类型选择函数。在他的情况下,在所有此类函数中,最好使用带有 sizeof 运算符的表达式而不是直接使用常量,因为代码是重复的。
      • 有趣,我从未听说过。也许在答案中包括一个例子!
      【解决方案4】:

      我有一个指向 c 中的数组的指针,我想遍历它,但我不知道大小:

      如果你真的有一个指向数组的指针,那么你很幸运,因为指向数组的指针的类型包含有关数组大小的信息。

        int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
        int (*pointer_to_an_array)[7] = &some_array;
      
        #define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
        for (size_t i = 0; i < N; i++) {
          printf("%d\n", (*pointer_to_an_array)[i]);
        }
      
        
      

      不幸的是,对于int *array;,代码没有指向数组的指针,但指向int 的指针和有关some_array[] 的原始数组大小的信息无法通过array.

      int some_array[7] = {1,2,3,4,5,6,7};
      int *array = some_array; // Not a pointer to an array
      

      在另一个变量中携带有关数组大小的信息。

      size_t some_array_n = sizeof some_array/ sizeof some_array[0];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-13
        • 1970-01-01
        • 2014-09-19
        • 2019-04-14
        • 2020-10-16
        • 2011-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多