3

对于以下场景,如何a通过指针获取数组的大小 (3) c?解决这类问题的模式是什么?

struct struct_point {
  int x;
  int y;
  int z;
};

typedef struct struct_point point;

int test_void_pointer () {
  point a[3] = {{1, 1, 1}, {2, 2, 2}};
  void * b;
  point * c;
  b = a;
  c = b;
  /* get_size_p (c) */
}
4

3 回答 3

7

你不能。指针只是一个地址,一个数字,除了它的类型,它不包含任何关于它所指向的数据的信息。


旁注:这就是为什么他们说“数组衰减为指针”。它们“衰减”是因为与数组相比,指针本质上包含的信息更少。

正如 nims 在将数组传递给函数时在注释中指出的那样,它会自动衰减为指向第一个元素的指针——并且sizeof在函数中执行不会产生预期的结果。顺便说一句,还有一个关于这个的C 常见问题解答

于 2013-10-04T16:35:29.670 回答
4

在 C 中,没有关于数组大小的信息与数组一起存储。您必须知道安全地使用它有多大。

有一些技术可以解决这个问题。如果数组是在当前范围内静态声明的,则可以将大小确定为:

size_t size = (sizeof(a) / sizeof(a[0]);

如果您不想每次添加元素时都更新大小,这很有用:

struct point a[] = {{1, 1, 1}, {2, 2, 2}};
size_t size = (sizeof(a) / sizeof(a[0));

但是,如果您有一个任意数组,该数组是从其他地方传入的,或者如您的示例中那样转换为指针,您将需要某种方法来确定其大小。执行此操作的常用方法是将大小与数组一起传递(作为单独的参数,或作为包含数组的结构),或者如果数组的类型可以包含一个标记值(一个值给定类型是无效的),您可以分配一个比您需要的数组大一个的数组,在数组的末尾添加一个哨兵,并使用它来确定您何时到达终点。

以下是您如何将长度作为单独的参数传递:

struct point myfunction(struct point array[], size_t n) {
    for (size_t i = 0; i < n; ++i) {
        struct point p = array[i];
        // do something with p ...
    }
}

或作为包含长度的结构:

struct point_array {
    size_t n;
    struct point elems[];
}
struct point myfunction(struct point_array a) {
    for (size_t i = 0; i < a.n; ++i) {
        struct point p = a.elems[i];
        // do something with p ...
    }
}

可能很难直接将标记值与数组一起使用struct point,因为没有明显的无效值仍然属于同一类型,但它们通常用于字符串(其数组char以字符结尾'\0')和数组由空指针终止的指针。我们可以struct point通过存储指向我们结构的指针而不是将它们内联存储在数组中来使用它:

struct point *myfunction(struct point *a[]) {
    for (size_t i = 0; a[i] != NULL; ++i) {
        struct point *p = a[i];
        // do something with p ...
    }
}
于 2013-10-04T17:03:35.257 回答
0

有一种方法可以确定数组的长度,但为此您必须用另一个元素(例如 -1)标记数组的结尾。然后遍历它并找到这个元素。这个元素的位置就是长度。

于 2013-10-04T16:46:01.693 回答