原函数是《The C programint  language 》5.11文本行排序的程序,如下:

void qsort(void *v[], int left, int right, int (*comp)(void *,void *))
{
int i,last; if( left >= right)
return; swap(v,left,(left+right)/2);
last = left;
for(i = left + 1; i <= right; ++i)
if(comp(v[i],v[left]) < 0)
swap(v,++last,i);
swap(v,left,last);
qqsort(v,left,last-1,comp);
qqsort(v,last+1,right,comp);
}

该函数有以下特点:

1. 参数  void *v[] ,这是把main函数传递的实参转换为通用的void * * 类型的形参,那对于实参的需要自己强制转换,比如把  char * lineptr[] 传递给  v,必须这样(void ** )lineptr,

那为什么能这样转化

1. 任意的类型都可以赋给相应的void类型的

2. 该void的类型也可以强制转换为该类型

那为什么要这样转换

1. 这样转换可以满足函数通用性的要求,任何类型都可以转换为相应的void类型,相对于这个程序,把char 转换为 void,只要在comp模型中提供了comp(char *,char *)去调用,就把void 转换为 char 类型进行运算,符合程序通用化的要求;

2. 之所以可以用void的1阶以上指针,是因为各种类型的地址字节都是固定了,win32用4个字节表示指针,所以只要该函数内的void类型的运算都是对地址的运算都可以,不能对相应的void的类型进行四则和取值运算,因为它虽然指向对应变量的首地址,但是他不知道该地址指向的数据类型,所以除了地址运算其他的都不能进行,也就是说使用这种转换函数,必须保证该函数内除了地址运算外,不能进行其他的运算。

还有对于 形参void * v [] 去代替实参  (void **)lineptr,对于一个指向void * 的数组来说,之所以行,是因为v[1]是可以计算,数组中存的都是指针,固定4个字节,v[1] 的地址 v + 4就行了,由因为它指向的是地址,v[1]指向一个地址,改地址又是4个字节的大小,只有这些是可以确定,其他的不行,不能对v[1][1],因为v[1]是个地址,但是这个地址指向的内容的类型不能判定,不知道把改地址指向的那块数据取几个字节,转换什么类型,都不得而知。

还有个强制转换问题:

char  s[3][3];

void ** p = s;

把p转换为s的    ((char (*)[3])p)[0] = s[0]

完整的程序见:http://blog.csdn.net/chenyiming_1990/article/details/9382177

通过qsort(void * lineptr[], int left, int rifht, int (*comp)(void *, void *))解读指针函数和void指针的更多相关文章

  1. public void onItemClick(AdapterView arg0, View view, int position,long arg3)详解【整理自网络】

    参考自: http://blog.csdn.net/zwq1457/article/details/8282717 http://blog.iamzsx.me/show.html?id=147001 ...

  2. signal函数:void (*signal(int,void(*)(int)))(int);

    http://blog.chinaunix.net/uid-20178794-id-1972862.html signal函数:void (*signal(int,void(*)(int)))(int ...

  3. Java JNA (四)—— void**、void*、char**、char*、int*等类型映射关系及简单示例

    ByReference类有很多子类,这些类都非常有用. ByteByReference.DoubleByReference.FloatByReference. IntByReference.LongB ...

  4. 编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试Stud

    package zuoye; public class student { int age; String name; int stuNO; void outPut() { System.out.pr ...

  5. (int &)a 和(int)a

      [cpp] view plain copy float a = 1.0f;     cout < < (int)a < < endl;     cout < < ...

  6. C++中int *p[4]和 int (*q)[4]的区别

    这俩兄弟长得实在太像,以至于经常让人混淆.然而细心领会和甄别就会发现它们大有不同. 前者是指针数组,后者是指向数组的指针.更详细地说. 前: 指针数组;是一个元素全为指针的数组.后: 数组指针;可以直 ...

  7. open_clientfd(char* hostname,int port)和open_listenfd(int port)

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h&g ...

  8. 5.编写Java应用程序。首先,定义描述学生的类——Student,包括学号(int)、 姓名(String)、年龄(int)等属性;二个方法:Student(int stuNo,String name,int age) 用于对对象的初始化,outPut()用于输出学生信息。其次,再定义一个主类—— TestClass,在主类的main方法中创建多个Student类的对象,使用这些对象来测 试St

    Student类: package com.bao; public class Student { int stuNo;String name,sex;int age,weight; Student( ...

  9. int *p[4]与int (*q)[4]的区别

    以上定义涉及两个运算符:“*”(间接引用).“[]”(下标),“[]”的优先级别大于“*”的优先级别. 首先看int *p[4],“[]”的优先级别高,所以它首先是个大小为4的数组,即p[4]:剩下的 ...

随机推荐

  1. iOS MapKit导航及地理转码辅助类

    头文件: #import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface DirectionRou ...

  2. 关于springmvc 方法注解拦截器的解决方案,多用于方法的鉴权

    最近在用SpringMvc写项目的时候,遇到一个问题,就是方法的鉴权问题,这个问题弄了一天了终于解决了,下面看下解决方法 项目需求:需要鉴权的地方,我只需要打个标签即可,比如只有用户登录才可以进行的操 ...

  3. 安德鲁斯Selector简介

    <? xml version="1.0" encoding="utf-8"? > <selector xmlns:android=" ...

  4. 生产环境使用Nginx+uwsgi部署Django

    在本地运行django应用相对来说还是挺方便的,使用自带的runserver启动即可.如果在生产环境部署django,就要多考虑一些问题了.比如静态文件处理,安全,效率等等 在网上找到了不错的部署的教 ...

  5. HTML 5 在Web SQL 使用演示样本

    Web sql 这是一个模拟数据库浏览器.可以使用JS操作SQL完成数据读取和写入,但是这件事情并不多,现在支持的浏览器,而其W3C规格已经停止支持.外形似它的前景不是很亮. W3C 规范:http: ...

  6. PLSQL-Developer数据库连接工具使用方法

    PLSQL-Developer数据库连接工具使用方法 该方法适用于本机未安装Oracle客户端的情况下如何让连接到数据库.经过本人亲自测试绝对可以连接.前提是您安装的版本没有问题,如您安装的版本有问题 ...

  7. mediawiki在windows下的安装

    mediawiki在windows下的安装 对于刚接触wiki的朋友们来说,配置一个服务器环境,安装并运行mediawiki是一件很麻烦的事情,在这里,我尽量用通俗易懂的语言,介绍mw(mediawi ...

  8. IS_EER分析

    下面我们就来具体分析一下这段代码,看看内核中的巧妙设计思路. 要想明白IS_ERR(),首先理解要内核空间.所有的驱动程序都是运行在内核空间,内核空间虽然很大,但总是有限的,而在这有限的空间中,其最后 ...

  9. How feedback work for your improvement

    Why generally feedback is the perspective from others for some event. In China there is story,some k ...

  10. Ubuntu中的.bashrc文件

    /etc/profile:此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.并从/etc/profile.d目录的配置文件中搜集shell的设置./etc/bashrc:为每一个运 ...