关于qsort第四个参数,函数指针作参数的一点思考 yongmou

  qsort函数原型:void qsort(void *base, size_t count, size_t size,

    int (*compar)(const void * element1, const void *element2));

  compar函数参数可以定义为(const void *)类型,这需要在 compar函数内部cast为所处理类型。如:

1 struct elem{
2 int key;
3 int data;
4 } table[COUNT];
5
6  int key_compare(const void *e1, const void *e2){
7 int v1 = ((struct elem *)e1)->key;
8 int v2 = ((struct elem *)e2)->key;
9 return (v1<v2) ? -1 : ((v1>v2) ? 1 : 0);
10 }

  也可以直接定义为所处理类型的指针,在调用qsort函数时需要将compar函数cast为(int (*)(const void *, const void *)。如:

1 int key_compare1(const struct elem *e1, const struct elem *e2){
2 int v1 = e1->key;
3 int v2 = e2->key;
4 return (v1<v2) ? -1 : ((v1>v2) ? 1 : 0);
5 }
6
7 函数调用语句:
8 qsort(table, COUNT, sizeof(struct elem),
9 (int (*)(const void *, const void *))key_compare1);

  一开始我以为这样不正确,因为qsort函数内部还是会调用compar的,这样类型就不匹配了啊!

  其实是正确的,因为这种类型检查是编译时做的(gcc 使用-c选项)

  链接时不做类型检查,只要能找到那个函数名就行;

  运行时取参数更不管这些东西了,是用esp+offset直接抓来的。

  函数原型是ANSI C才加进来的东西,K&R C第一版中,只要有个函数名就行了。

  下面一个小例子,你会看出端倪:

  文件:tmp.c

1 #include <stdio.h>
2 int f(void *a, void *b){
3 printf("Call f\n");
4 return 0;
5 }

  编译命令: gcc -c tmp.c

  文件:main.c

1 int main(){
2 f();
3 return 0;
4 }

  编译命令:gcc -c main.c

  链接生成可执行文件:gcc tmp.o main.o 

  执行:

  [lym@localhost tmp]$ ./a.out

  Call f

  一点问题都没有。

  nm 看一下符号表:

[lym@localhost tmp]$ nm tmp.o
00000000 T f
         U puts
[lym@localhost tmp]$ nm main.o
         U f
00000000 T main
[lym@localhost tmp]$ nm a.out
080483b4 T f
080483d0 T main
         U puts@@GLIBC_2.0
原文地址:https://www.cnblogs.com/liyongmou/p/1962051.html