【问题标题】:How to traverse an array parameter as void pointer如何将数组参数作为空指针遍历
【发布时间】:2016-01-14 06:03:50
【问题描述】:

我有类似的“通用”过程,如 qsort,它有一个 void 指针(指向一个数组)和一个函数指针参数。这个函数应该适用于任何类型的数组。

例子:

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]

经过一些研究,我发现像这样使用 void 指针是一种不好的做法。 (例如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 *) 吗?

【问题讨论】:

  • 不管类型如何,使用 char 并不比使用 void 更多:) char 上的算术可以完成这项工作(使用 size 步骤)。

标签: c gcc gcc-pedantic


【解决方案1】:

使指针无效只是带走了指针的“上下文”——也就是说,系统应该如何看待指针或指针所持有的任何内容。

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

出于这个原因,唯一的方法是将指针转换为某个东西并执行它 - 我不推荐它,除非您非常清楚指针得到了什么。 void 指针是相当黑暗的编程。

【讨论】:

  • @Aaron 我相信做事的最好方法是始终分配类型。这真的取决于你想要达到的目标。
  • 在这种情况下是不可能的。
【解决方案2】:

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

Void * 算术没有定义。将 1 添加到 void 指针是什么意思?大多数编译器(如果允许)将其视为按 sizeof(char) 递增(“下一个字节”),但会警告您。

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

【讨论】:

  • 谢谢。我也很好奇为什么要转换为 char,我在您的链接中找到了答案:“char 类型很方便,因为它的定义大小为 1 个字节。”
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2021-05-29
    • 1970-01-01
    • 2013-05-20
    • 2012-01-24
    • 2018-06-30
    • 2012-11-06
    • 2018-05-14
    • 1970-01-01
    相关资源
    最近更新 更多