zoukankan      html  css  js  c++  java
  • 关于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
    
  • 相关阅读:
    K近邻法
    决策树
    朴素贝叶斯
    Git学习笔记
    【原】maven web项目eclipse搭建
    三道面试题
    72-74 流的考点
    57-71 容器考点
    四 java web考点
    五 数据库考点
  • 原文地址:https://www.cnblogs.com/liyongmou/p/1962051.html
Copyright © 2011-2022 走看看