如何通过指针获取数组的大小?

时间:2013-10-04 16:33:01

标签: c pointers

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

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) */
}

3 个答案:

答案 0 :(得分:7)

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


旁注:这就是他们说“数组衰减到指针”的原因。它们“衰变”,因为与数组相比,指针本身保存的信息较少。

当nims在将数组传递给函数时在注释中指出,它会自动衰减到指向第一个元素的指针 - 并且在函数中执行sizeof不会产生预期的结果。顺便提一下,这也是一个C FAQ

答案 1 :(得分: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));

但是如果你有一个任意数组,它已经从其他地方传入,或者像你的例子那样转换为指针,你需要一些方法来确定它的大小。通常的方法是将大小与数组一起传递(作为单独的参数,或作为包含数组的结构),或者如果数组的类型可以包含sentinel值(值为如果给定的类型无效,你可以分配一个比你需要的更大的数组,将一个标记添加到数组的末尾,然后用它来确定你何时到达终点。

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

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数组的sentinel值,因为没有明显的无效值仍然是相同的类型,但它们通常用于字符串({{{{ 1}}由char字符终止),以及由空指针终止的指针数组。通过存储指向结构的指针,我们可以将它与'\0'一起使用,而不是将它们内联存储在数组中:

struct point

答案 2 :(得分:0)

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