📄 qsort2.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN"><!-- This collection of hypertext pages is Copyright 1995-2005 by Steve Summit. --><!-- Content from the book "C Programming FAQs: Frequently Asked Questions" --><!-- (Addison-Wesley, 1995, ISBN 0-201-84519-9) is made available here by --><!-- permission of the author and the publisher as a service to the community. --><!-- It is intended to complement the use of the published text --><!-- and is protected by international copyright laws. --><!-- The on-line content may be accessed freely for personal use --><!-- but may not be published or retransmitted without explicit permission. --><!-- --><!-- this page built Sat Dec 24 21:47:46 2005 by faqproc version 2.7 --><!-- from source file libsort.sgml dated Sun Feb 3 13:14:17 2002 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/lib/qsort2.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:58:59 GMT --><head><meta name=GENERATOR content="faqproc"><title>Question 13.9</title><link href="qsort1.html" rev=precedes><link href="listsort.html" rel=precedes><link href="index.html" rev=subdocument></head><body bgcolor="#ffffff"><a href="qsort1.html" rev=precedes><img src="../images/buttonleft.gif" alt="prev"></a><a href="index.html" rev=subdocument><img src="../images/buttonup.gif" alt="up"></a><a href="listsort.html" rel=precedes><img src="../images/buttonright.gif" alt="next"></a> <a href="../index-2.html"><img src="../images/buttontop.gif" alt="top/contents"></a><a href="../search.html"><img src="../images/buttonsrch.gif" alt="search"></a><hr><p><!-- qbegin --><h1>comp.lang.c FAQ list<font color=blue>·</font><!-- qtag -->Question 13.9</h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Now I'm trying to sort an array of structureswith <TT>qsort</TT>.My comparison function takes pointers to structures,but the compilercomplainsthat the function isof the wrong type for <TT>qsort</TT>.How can I cast the function pointer to shut off the warning?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Theconversionsmust be in thecomparison function,whichmust be declared as accepting ``generic pointers''(<TT>const void *</TT>)as discussedin question<a href="qsort1.html">13.8</a> above.For a hypotheticallittledate structure<pre>struct mystruct { int year, month, day;};</pre>thecomparison functionmight look like<a href="compare.html" rel=subdocument>[footnote]</a><pre>int mystructcmp(const void *p1, const void *p2){ const struct mystruct *sp1 = p1; const struct mystruct *sp2 = p2; if(sp1->year < sp2->year) return -1; else if(sp1->year > sp2->year) return 1; else if(sp1->month < sp2->month) return -1; else if(sp1->month > sp2->month) return 1; else if(sp1->day < sp2->day) return -1; else if(sp1->day > sp2->day) return 1; else return 0;}</pre>(The conversionsfrom generic pointersto <TT>struct mystruct</TT> pointershappen in the initializations<TT>sp1 = p1</TT> and <TT>sp2 = p2</TT>;the compiler performs theconversions implicitlysince<TT>p1</TT> and <TT>p2</TT> are<TT>void</TT> pointers.)</p><p>For this version of <TT>mystructcmp</TT>,the call to <TT>qsort</TT> might look like<pre>#include <stdlib.h>struct mystruct dates[NDATES];int ndates;/* ndates cells of dates[] are to be sorted */qsort(dates, ndates, sizeof(struct mystruct), mystructcmp);</pre></p><p>If,on the other hand,you're sorting pointers to structures,you'll need indirection,as in question<a href="qsort1.html">13.8</a>;thehead ofthecomparison function wouldlooklike<pre>int myptrstructcmp(const void *p1, const void *p2){ struct mystruct *sp1 = *(struct mystruct * const *)p1; struct mystruct *sp2 = *(struct mystruct * const *)p2;</pre>and the call would look like<pre>struct mystruct *dateptrs[NDATES];qsort(dateptrs, ndates, sizeof(struct mystruct *), myptrstructcmp);</pre></p><p>To understand why the curiouspointer conversionsin a <TT>qsort</TT> comparison function are necessary(and why a cast of the function pointer when calling<TT>qsort</TT>can't help),it's useful to think about how <TT>qsort</TT> works.<TT>qsort</TT> doesn't know anything about the type orrepresentation of the data being sorted:it just shuffles around little chunks of memory.(All it knows about the chunks is their size,which you specifyin <TT>qsort</TT>'s third argument.)To determine whether two chunks need swapping,<TT>qsort</TT> calls your comparison function.(To swap them,ituses the equivalent of <TT>memcpy</TT>.)</p><p>Since <TT>qsort</TT> deals in a generic waywith chunks of memory of unknowntype,it uses generic pointers(<TT>void *</TT>)to refer to them.When <TT>qsort</TT> calls your comparison function,it passes as argumentstwo generic pointers to the chunks to be compared.Since it passes generic pointers,your comparison function must<em>accept</em> generic pointers,andconvertthe pointers back to their appropriate typebefore manipulating them(i.e. before performing the comparison).A <TT>void</TT> pointer is not the same type as a structure pointer,and on some machines it may have a different size or representation(which is why these casts are required for correctness).</p><p>If you were sorting an array of structures,and had a comparison function accepting structure pointers:<pre> int mywrongstructcmp(struct mystruct *, struct mystruct *);</pre>and if you called <TT>qsort</TT> as<pre> qsort(dates, ndates, sizeof(struct mystruct), (int (*)(const void *, const void *))mywrongstructcmp); /* WRONG */</pre>thecast<TT>(int (*)(const void *, const void *))</TT>would do nothingexcept perhapssilence the message from the compiler telling you that thiscomparison functionmay<em>not</em> work with <TT>qsort</TT>.Theimplicationsof any cast you usewhen calling qsortwill have been forgottenby the time <TT>qsort</TT>gets around to calling your comparison function:it will call them with <TT>const void *</TT> arguments,so that is what your function must accept.No prototype mechanism existswhich could operate down inside <TT>qsort</TT>to convert the <TT>void</TT> pointers to <TT>struct mystruct</TT> pointers just before calling <TT>mywrongstructcmp</TT>.</p><p>In general,it is a bad idea to insert casts just to``shut the compiler up.''Compiler warnings are usually trying to tell you something,and unless you really know what you're doing,you ignore ormuzzlethem at your peril.See also question <a href="../ptrs/genericpp.html">4.9</a>.</p><p><a href="sd14.html" rel=subdocument>Additional links</a></p><p>References:ISO Sec. 7.10.5.2<br>H&S Sec. 20.5 p. 419<br></p><!-- aend --><p><hr><a href="qsort1.html" rev=precedes><img src="../images/buttonleft.gif" alt="prev"></a><a href="index.html" rev=subdocument><img src="../images/buttonup.gif" alt="up"></a><a href="listsort.html" rel=precedes><img src="../images/buttonright.gif" alt="next"></a> <a href="../questions.html"><img src="../images/buttontop.gif" alt="contents"></a><a href="../search.html"><img src="../images/buttonsrch.gif" alt="search"></a><br><!-- lastfooter --><a href="../about.html">about this FAQ list</a> <a href="../eskimo.html">about eskimo</a> <a href="../search.html">search</a> <a href="../feedback.html">feedback</a> <a href="copyright.html">copyright</a><p>Hosted by<a href="http://www.eskimo.com/"><img src="../../www.eskimo.com/img/link/eskitiny.gif" alt="Eskimo North"></a></body><!-- Mirrored from c-faq.com/lib/qsort2.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:58:59 GMT --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -