如何将数组参数作为空指针遍历

How to traverse an array parameter as void pointer

我有一个类似于 qsort 的 "generic" 过程,它有一个空指针(指向一个数组)和一个函数指针参数。此函数适用于任何类型的数组。

示例:

void do_something(void * array, int count, int size, void (*test)(const void*)){
    int i;
    for(i=0; i<count; i++){
        test(array + (index * size));
    }
}

然而,这给了我以下警告(gcc test.c -pedantic-errors):

error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]

经过一些研究,我发现像这样使用空指针是一种不好的做法。 (例如 Pointer arithmetic for void pointer in C

那么标准库是如何为 qsort 做这种事情的呢?查看此代码:(http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c),我看到以下内容:

void
_quicksort (void *const pbase, size_t total_elems, size_t size,
        __compar_fn_t cmp)
{
  register char *base_ptr = (char *) pbase;
  ....
  char *lo = base_ptr;
  char *hi = &lo[size * (total_elems - 1)];
  ...
}

无论实际类型如何,它们都转换为 (char *) 吗?

不完整数据类型的指针运算 void 是不合法的,这就是编译器所抱怨的。

正如您在 _quicksort() 中看到的那样,指针是一个常量指针,因此您无法修改指针指向的地址。 void 指针上没有发生算术运算。

我问过类似的问题Can I do arithmetic on void * pointers in C?

Void * 未定义算术。空指针加 1 是什么意思?大多数编译器(如果允许的话)将其视为递增 sizeof(char) ("the next byte") 但会警告您。

所以正确的做法是明确地让它做你想做的事 -> 转换为 char* 并增加它

使指针无效只会带走指针的 "context" - 也就是说,系统应该如何看待指针或指针持有的任何内容。

因此,编译器不会对 void 指针进行算术运算。为了进行指针运算,编译器需要知道指针的类型,以便它可以进行正确的转换(如果指针包含一个 int,它不会对 32 位进行加法,或者至少它会让你知道出问题了!)。

出于这个原因,唯一的方法是将指针指向某物并执行它 - 我不会推荐它,除非你非常清楚指针的含义。空指针是相当黑暗的编程。