简体   繁体   English

计算未知类型数组的元素

[英]Count elements of an unknown type array

Hello i am trying to write a function which return the number of elements of the array passed as parameter, the function have to work on an array of any type . 您好,我正在尝试编写一个函数,函数返回作为参数传递的数组元素的数量,该函数必须在任何类型的数组上工作

I tried this: 我尝试了这个:

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;
}

As you can guess, it doesn't work. 如您所料,它不起作用。

In fact it doesn't even compile, i get these errors: 实际上它甚至不编译,我得到这些错误:
Error: Illegal indirection. 错误:非法的间接访问。 < while(*end != NULL) > <while(* end!= NULL)>
Error: void * : size unknown. 错误:无效*:大小未知。 < while(*end != NULL) > <while(* end!= NULL)>
Error: void * : size unknown. 错误:无效*:大小未知。 < return end - array > <返回端-数组>

First, could you tell me if what i am trying to do is possible? 首先,您能告诉我我想做的事是否可行吗?
Second, is the way i am trying to achieve this makes sense , or am i completely missing the point? 其次, 我试图实现这一目标的方法是否有意义 ,还是我完全忘记了要点?
Then, why do i get these errors, what does they means? 那么, 为什么我会得到这些错误,它们意味着什么?

Thanks for your help! 谢谢你的帮助!

As C does not pass arrays, nb_elems(void* array) received a pointer . 由于C不传递数组,因此nb_elems(void* array)收到了一个指针 The void *pointer does not know how many elements (nor the type) which its points to. void *pointer不知道其指向多少个元素(也不包括类型)。

Since it needs to "work on an array of any type", code needs to define how to compare an arbitrary type with NULL . 由于它需要“处理任何类型的数组”,因此代码需要定义如何将任意类型与NULL比较。

To your function, you need to pass the pointer, the size of an array element and a function to use to test against 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;
}

No, the way your are doing it is not possible, because to do pointer arithmetic (here the ++ and the - ) the compiler has to know the size of the base type of the array. 不,您的操作方式是不可能的,因为执行指针算术(这里是++- )时,编译器必须知道数组基本类型的大小。

Also void* is a pointer to void , that is to a "non-type". 同样, void*是指向void的指针,即指向“非类型”的指针。 So *end has type void and you can't compare it to anything, in particular not to NULL , which could be a pointer type or an integer. 因此, *end类型为void ,您无法将其与任何东西进行比较,尤其是不能与NULL ,后者可以是指针类型或整数。 Just use 0 if you compare a base type for being zero. 如果将基本类型比较为零,则只需使用0

Before starting to even try to do this for pointers of any type, you should try the same for pointers to a known type, say unsigned or double . 在甚至尝试对任何类型的指针执行此操作之前,您应该对指向已知类型的指针(例如unsigneddouble尝试相同的操作。 If you change your code with that in mind, it has good chances to work. 如果您牢记这一点更改代码,那么它就有很好的机会工作。

The reason your code doesn't compile, is because of the fact that the compiler cannot determine the size of a void. 您的代码无法编译的原因是由于编译器无法确定void的大小。 Take for example the ++ operator. 以++运算符为例。 We could roughly translate this to: 我们可以将其大致翻译为:

end = end + sizeof(void);

The size of a void is not defined, so the compiler cannot generate any code for this, giving you one error. 未定义空隙的大小,因此编译器无法为此生成任何代码,从而给您一个错误。

Next you try to dereference a void pointer. 接下来,您尝试取消引用空指针。 This would give you something with the type void. 这会给你一些类型为void的东西。 But since a void does not represent anything (it represents nothing), the compiler cannot tell what this should be. 但是由于void不代表任何内容(它不代表任何内容),因此编译器无法确定应为什么。 You then use the equality operator to compare nothing to NULL. 然后,您可以使用相等运算符将任何内容都不与NULL比较。 You cannot compare nothing to something, so this will generate an error. 您无法将某物与任何事物进行比较,因此会产生错误。

In C, it is impossible to implement a function that would do something like this, simply because of the fact that you cannot tell what the type of the void* will be. 在C语言中,仅由于您无法确定void *的类型,就不可能实现执行此类操作的函数。 You at least need to know the type your passed to your function and what type-specific value will be used to terminate the array. 您至少需要知道传递给函数的类型以及将用于终止数组的特定于类型的值。 C does not offer this functionality, making the implementation of such a function impossible. C没有提供此功能,因此无法实现此功能。

because you are checking != NULL i suppose you have an array of pointers. 因为您正在检查!= NULL我想您有一个指针数组。 with array of pointer your code could work because you know the size of pointers even if it is a void pointer. 使用指针数组,您的代码可以工作,因为您知道指针的大小,即使它是空指针也是如此。

if my assumptions were right you could code it like this: 如果我的假设是正确的,则可以这样编写:

int nb_elems(void** array) {
    void** end = array;
    while(*end != NULL) {
        end++;
    }
    return end - array;
}

but this code only works with pointer to pointer or array of pointer. 但是此代码仅适用于指向指针的指针或指针数组。


usage: 用法:

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));

the example prints 2 该示例打印2

如果您有一个实际的数组,而不是一个指针,则可以使用sizeof(array) / sizeof(array[0])确定其中的元素数量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM