1

嘿,我有这种类型的东西

eph_t *a;

如您所见,类型是 eph_t。它是 C 中的一个数组,但我不知道数组的大小,也不知道数组的结束元素是什么。有没有办法,我可以遍历整个数组,因为我想将数组中每个元素的值分配给某个东西。

我可以考虑哪些选择?如果您无法理解问题中的某些内容,请发表评论,以便我通知您。

4

4 回答 4

7

如果您不知道数组的大小,那么迭代它是不安全的。每当您尝试读取最后一个元素之外的元素时,您都会得到未定义的行为。除非您知道数组的大小,否则您无能为力。

于 2013-08-28T10:26:34.017 回答
5

正如其他人所说,当您不知道数组的结尾时,迭代数组是不安全的。这通常通过以下方式解决。

  1. 例如,如果您有权访问数组声明 ( int a[10];)。您可以使用sizeof运算符来确定数组的大小。请注意,将指向数组的指针传递给函数时,这将不起作用。
  2. 使用数组的函数通常会采用直接大小或某种方式来推断大小作为函数的额外参数(memset是一个很好的例子)
  3. 数组可能有一个特殊的终止元素(通常最后是一个 NULL 或 0 元素),这意味着你不能迭代超出(C 字符串是很好的例子)

因此,如果您正在设计一个以数组为参数的函数,请使用上述模式。如果您使用的函数不使用上述模式之一,请将问题作为错误报告给库设计者。

于 2013-08-28T10:37:47.617 回答
1

C中的指针只是一个地址。当用作数组时,您必须(通过其他方式)计算出数组的长度。

许多处理数组的库都具有接受指向数组的指针及其大小的函数。例如qsort(3)想要第二个参数给出要排序nmemb的数组元素的数量base(第一个参数)。qsort

或者,您可以使用灵活的数组成员(在 C99 中)并传递(并在相关时返回)指向类似结构的指针,而不是只传递一个指针

  struct eph_tuple_st {
     unsigned len;
     eph_t* ptrtab[];
  };

具有灵活数组ptrtab字段具有len元素的约定。

最后,正如其他人所建议的,您可以使用标记值(即空字)来结束数组。通常我不建议这样做(缓冲区溢出的风险,计算实际大小的时间复杂度)。

FWIW,最近的 C++ 有std::dynarray (C++2014) 和std::vector,而 Ocaml 有Array模块。您可以切换到一些更友好的编程语言。

于 2013-08-28T10:26:41.173 回答
1

您可以保留数组的第一个元素来存储大小

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int x, y;
    double z;
} eph_t;

static void temp(eph_t *a)
{
    size_t n;

    memcpy(&n, a - 1, sizeof(size_t)); /* get size (stored in a - 1) */
    printf("Count = %zu\n", n);
}

int main(void)
{
    const size_t n = 5;
    eph_t a[n + 1]; /* allocate space for 1 more element */

    memcpy(&a[0], &n, sizeof(size_t)); /* now the first element contains n */
    temp(a + 1); /* skip first element */
    return 0;
}
于 2013-08-28T12:17:46.540 回答