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

描述:
这是The C Programming Language书中实现多行文本排序的部分代码。
实现排序的有两个函数,自定义的numcmp和库函数strcmp。
lineptr是一个二级指针,用来存储多行文本。

全部代码地址:
https://github.com/WebFeng/learn_c/blob/master/e_arr_point/sort_textline2.c

代码部分实例:

char *lineptr[MAXLINES];

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

int numcmp(char *s1, char *s2)

问题:
1、(第二行代码)为什么要把lineptr转成void类型?
2、lineptr转成void类型后,由于numcmp和strcmp的参数类型与void不符,则需要用(int (*)(void *, void *))把函数参数强制转换成void类型。那么请问此处的强制类型转换只是为了让编译器知道函数的形参类型与实参类型相符么?C的底层究竟做了什么?是真的把原本接收char *类型的函数改成了接收void *类型了么?
3、直接把函数参数改写成void *,然后在numcmp中把参数转int,在strcmp中把参数转char,这样就不用函数的强制类型转换了。numcmp接收void *类型参数会不会让代码看起来很怪?

阅读 4.3k
2 个回答
1:为什么要把lineptr转成void类型?
因为声明,void *lineptr[] 和 void **lineptr 是等价的

void qsort1(void *lineptr[] ..... )

至于 char** 为什么和 void ** 不兼容
不管你是几级指针,归根到底都是指针,所以都能和void *兼容,void * 本来就是一个抽象的指针类型
char **a;
void *ptr = a;
char ***a
void ptr = a; // 都是完全兼容的

2 :函数的强制类型转换只是为了让编译器知道函数的形参类型与实参类型相符么?C的底层究竟做了什么?是真的把原本接收char 类型的函数改成了接收void 类型了么?

void qsort1(..... int (*comp)(void *, void *));
int numcmp(char *, char *);
int strcmp( const char  *, const  char *);
numcmp  与 comp 类型兼容
但是 strcmp 却与 comp 不兼容 

strcmp 与 comp 不兼容的原因
const void * 表示你可以不能修改 指针指向的内容
void * 表示你可以修改


不知道你有没有看过qsort库函数的源代码

void __cdecl qsort (  
    void *base,  
    size_t num,  
    size_t width,  
    int (__cdecl *comp)(const void *, const void *)  
    )    

第一:不管整形数组,还是字符串数组,都是void 接受,而你却是void *
第二 :comp 函数的参数是const void *

不管是库函数strcmp , 还是你自己写的比较函数,最好都用 加上const 

修改以后的代码

void * 代表的是任意类型指针啊,用在这里的意思就是能够接受任意类型指针,为什么还要转换?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进