您好我正在尝试编写一个函数,它返回作为参数传递的数组元素的数量,该函数必须处理任何类型的数组。
我试过这个:
int nb_elems(void* array)
{
void* end = array;
while(*end != NULL) // The last element have to be null, it is not counted.
end++;
return end - array;
}
你可以猜到,它不起作用。
实际上它甚至没有编译,我得到这些错误:
错误:非法间接。 < while(* end!= NULL)>
错误:void *:大小未知。 < while(* end!= NULL)>
错误:void *:大小未知。 < return end - array>
首先,你能否告诉我我想做什么?
第二,是我试图实现这一点的方式,还是我完全忽略了这一点?
然后,为什么我会收到这些错误,这意味着什么?
谢谢你的帮助!
答案 0 :(得分:3)
由于C未传递数组,nb_elems(void* array)
收到指针。 void *pointer
不知道它指向的元素数量(也不是类型)。
由于它需要处理任何类型的数组",代码需要定义如何将任意类型与NULL
进行比较。
对于您的函数,您需要传递指针,数组元素的大小以及用于对NULL
进行测试的函数。
int nb_elems(void* array, size_t esize, int (*cmp)(void *ptr)) {
char *ptr = array;
int count = 0;
while (*cmp(ptr) == 0) {
ptr += esize;
count++;
}
return count;
}
答案 1 :(得分:1)
不,你做这件事的方式是不可能的,因为要做指针算术(这里是(5, 5)
和++
),编译器必须知道数组的基本类型的大小
同样-
是指向void*
的指针,即指向"非类型"。因此void
具有类型*end
,您无法将其与任何内容进行比较,特别是不能与void
进行比较,后者可能是指针类型或整数。如果您将基本类型与零进行比较,只需使用NULL
。
在开始尝试为任何类型的指针执行此操作之前,您应该尝试使用指向已知类型的指针,例如0
或unsigned
。如果你在考虑到这一点的情况下改变你的代码,它就有很好的工作机会。
答案 2 :(得分:1)
您的代码无法编译的原因是因为编译器无法确定void的大小。以++运算符为例。我们可以将其粗略地翻译为:
end = end + sizeof(void);
未定义void的大小,因此编译器无法为此生成任何代码,从而导致一个错误。
接下来,您尝试取消引用void指针。这会给你一些类型为void的东西。但由于void不代表任何东西(它代表什么都没有),编译器无法分辨它应该是什么。然后使用等于运算符将任何内容与NULL进行比较。你无法比较什么,所以这会产生错误。
在C中,不可能实现一个会做类似这样的事情的函数,仅仅是因为你无法分辨出void *的类型。您至少需要知道传递给函数的类型以及将用于终止数组的特定类型值。 C不提供此功能,因此无法实现此类功能。
答案 3 :(得分:1)
因为你正在检查!= NULL
我想你有一个指针数组。使用指针数组,你的代码可以工作,因为你知道指针的大小,即使它是一个无效指针。
如果我的假设是正确的,你可以像这样编码:
int nb_elems(void** array) {
void** end = array;
while(*end != NULL) {
end++;
}
return end - array;
}
但此代码仅适用于指向指针或指针数组的指针。
用法:
int** iptrs = (int**)malloc(3 * sizeof(int*));
iptrs[0] = (int*)malloc(sizeof(int));
*(iptrs[0]) = 42;
iptrs[1] = (int*)malloc(sizeof(int));
*(iptrs[1]) = 23;
iptrs[2] = NULL;
printf("%d", nb_elems(iptrs));
示例打印2
答案 4 :(得分:-1)
如果你有一个实际的数组,而不是一个指针,你可以使用sizeof(array) / sizeof(array[0])
来确定其中的元素数。