【问题标题】:qsort comparison: why const void *? [closed]qsort 比较:为什么是 const void *? [关闭]
【发布时间】:2016-01-11 02:46:43
【问题描述】:

我一直在通过 Kernighan 和 Pike 的《编程实践》一书中学习 C 编程。根据本书中的材料,我编写了一个小程序来对命令行中给出的整数数组进行排序。

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 30

char *progname;
int arr[MAXSIZE];

int icmp(int *, int *);

int main(int argc, char *argv[]) {
    int i;
    progname = argv[0];
    if (argc == 1) {
        fprintf(stderr, "usage: %s [int ...]\n", progname);
        exit(1);
    }
    for (i = 0; argc > 1 && i < MAXSIZE; i++, argc--) {
        arr[i] = atoi(argv[i+1]);
    }
    int n = i;
    qsort(arr, n, sizeof(*arr), icmp);
    for (i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    exit(0);
}

int icmp(int *p1, int *p2) {
    int v1 = *p1;
    int v2 = *p2;
    if (v1 < v2) {
        return -1;
    } else if (v1 == v2) {
        return 0;
    } else {
        return 1;
    }
}

是的,我的小程序似乎可以运行,我对此非常满意。然而,我的实现与书中给出的不同,它似乎没有正确地对整数进行排序。作者将 icmp() 定义为:

int icmp(const void *p1, const void *p2) {
    int v1, v2;
    v1 = *(int *) p1;
    v2 = *(int *) p2;
    if (v1 < v2) {
        return -1;
    } else if (v1 == v2) {
        return 0;
    } else {
        return 1;
    }
}

有什么关系?我的版本也从 gcc 发出警告:

warning: passing argument 4 of 'qsort' from incompatible pointer type

但是,具有正确指针类型的 qsort 没有正确排序我的整数!这里很迷茫。如果有人能启发我,我将非常感激。

【问题讨论】:

  • 传递错误类型的函数指针会在 qsort 尝试调用函数时触发未定义的行为。
  • “具有正确指针类型的 qsort 未正确排序我的整数”是什么意思?
  • 您可能应该在 qsort 参数中使用原始 argc-1 而不是 sizeof(arr*)。
  • @softwarenewbie7331:代码使用sizeof(*arr)(不是sizeof(arr*))。 qsort() 的第三个参数是每个元素的大小。整数的大小不取决于参数的数量——它固定为sizeof(int)sizeof(arr[0])sizeof(*arr),因此这是正确的。
  • 当我调整代码以便我可以在一次程序调用中测试两个比较器函数时,它们都“正常工作”,并且两者都正确排序了数据。我不得不使用大锤演员来避免你的icmp 的编译警告(演员是(int (*)(const void *, const void *))icmp),但仅此而已。是什么让您认为const void * 版本无法正常工作?

标签: c pointers int quicksort qsort


【解决方案1】:

qsort 比较:为什么是 const void *?

如果你查看qsort的原型,你会发现:

void qsort (void* base, size_t num, size_t size,
        int (*compar)(const void*,const void*));

如您所见,compar 函数的参数类型是 const void *

  • 它是void *,因为qsort 应该对泛型类型进行排序,而不仅仅是int。您可以对double 的数组、string 的数组、struct 的数组等进行排序。
  • const void * 是为了避免意外更改指针指向的数据(在 compar 函数内)。这只是关键字const 的典型安全措施。

【讨论】:

    猜你喜欢
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 2014-10-10
    相关资源
    最近更新 更多