问题编译K& R的例子

时间:2009-03-05 22:18:22

标签: c

我在编写本书第5.11节中介绍的示例程序时遇到了问题。我删除了大部分代码,只留下相关内容。

#define MAXLINES 5000
char *lineptr[MAXLINES];

void qsort1(void *lineptr[], int left, int right, int (*comp)(void *, void *));
int numcmp(char *, char *);

main(int argc, char *argv[]) {
    int numeric = 1;
    /* ... */
    qsort1((void**) lineptr, 0, 100, (int (*)(void*, void*))(numeric ? numcmp : strcmp));
}

void qsort1(void *v[], int left, int right, int (*comp)(void *, void *)) {
    /* ... */
}

int numcmp(char *s1, char *s2) {
    /* ... */
}

问题是代码无法编译(我正在使用Digital Mars编译器)。我得到的错误是:

        qsort1((void**) lineptr, 0, nlines - 1, (int (*)(void*, void*))(numeric
? numcmp : strcmp));

                 ^
go.c(19) : Error: need explicit cast to convert
from: int (*C func)(char const *,char const *)
to  : int (*C func)(char *,char *)
--- errorlevel 1

虽然我正确地粘贴了书中的代码,但声明一定有问题。我不知道做出正确的更改(关于函数指针的部分当然可以更广泛地编写)。

编辑:我应该提到我正在阅读本书的ANSI版本。

5 个答案:

答案 0 :(得分:9)

我认为错误来自于旧的C还不知道const的事实:strcmp有两个指针指向非const字符(char *)我想(这可能是它编译回来的原因,但不是你的编译器)。但是,现在strcmp需要char const*const char*是一回事)。将您的函数原型更改为:

int numcmp(char const*, char const*);

答案 1 :(得分:2)

qsort()bsearch()所期望的标准函数指针具有原型:

int comparator(const void *v1, const void *v2);

代码中定义的qsort1()期望:

int comparator(void *v1, void *v2);

代码中定义的比较器函数没有该原型,并且不同的函数指针类型之间没有自动转换。

因此,qsort1()的修正是:

  1. 介绍演员:(int (*)(void *, void *))
  2. 重写比较器:

    int numcmp(void *v1, void *v2)
    {
        char *s1 = v1;
        char *s2 = v2;
        ...
    }
    
    int str_cmp(void *v1, void *v2)  // Note new function name!
    {
        return(strcmp(v1, v2));
    }
    
  3. 显然,对qsort1()的调用会引用str_cmp而不是strcmp。作者试图避免使用中间函数,但与现在使用的(合法的)繁琐的编译器相违背。

    qsort()的标准版本需要一堆const限定符,与此答案的第一个版本一样。

答案 2 :(得分:2)

这是一个常见问题:)

以下行告诉qsort期望指向具有两个void *参数的函数的指针。不幸的是,strcmp需要两个不可修改的字符串,因此它的签名是

int (*comp)(const char*, const char*)

而不是你拥有的:

int (*comp)(void *, void *)

更改qsort1numeric的签名:

qsort1(void *v[], int left, int right, int (*comp)(const void *, const void *))

int numcmp(const char*, const char*)

答案 3 :(得分:1)

请注意,strcmp需要两个 const 参数,而numcmp不会。因此,这两个函数的类型不匹配,? :运算符会抱怨。

做其中一个:

  1. 根据constness
  2. 更改numcmp以匹配strcmp原型
  3. (int (*)(void*, void*))内推送? :强制转换,例如

    numeric ? (int (*)(void*, void*))numcmp : (int (*)(void*, void*))strcmp
    

答案 4 :(得分:0)

自从我完成任何纯C编程以来已经有一段时间了,我不确定新标准。

然而,转换为void **会创建一个指向指针的指针,其中函数需要指向数组的指针。当然,它们在内部是相同的,但强大的类型检查会将其视为错误。

重写qsort以接受**而不是* [],你应该没问题。