对于以下场景,如何通过指针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) */
}
答案 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。然后循环遍历它并找到这个元素。该元素的位置是长度。