?? qsort.msb.html
字號:
<html><!-- Mirrored from c-faq.com/lib/qsort.msb.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:03:00 GMT --><head><title></title></head><body>Newsgroups: comp.lang.c<br>From: msb@sq.sq.com (Mark Brader)<br>Subject: Re: Help qsort<br>Message-ID: <1994Apr29.005016.9449@sq.sq.com><br>Date: Fri, 29 Apr 94 00:50:16 GMT<p>> Is it also ok to declare the compare function with the correct types for<br>> what is being compared and then do a typecast to a defined type like<br>> '<TT>typedef int (*fptr)(const void *, const void *);</TT>' inside of the <TT>qsort</TT> call?<br>> Please no flames!<p>Well, at least a rebuke is certainly called for, because this exact questionis answered in the FAQ list. NO YOU CAN'T do that. Or more precisely, mostC implementations will get away with it, but it isn't a portable construct;code that uses it is not ``strictly conforming'' to the C standard.<p>> I got this directly out of the help pages for the<br>> Borland C++ 3.1 compiler.<p>Presumably those help pages are concerned only with what works on the machineswhere the compiler is used, or else their author simply got it wrong.<p>> It seems to work and don't see why it wouldn't<br>> be portable, but that's why I figured I'd ask anyway ;-).<p>Now this question, ``Why can't I?'', is one that's not in the FAQ list.<p>First consider this code, which I hope most people will agree isobviously wrong.<p><pre> void fun1(i) int i; { ... } main() { ... fun1 (3.14); ... }</pre><p>Why is it wrong (other than ``because the standard says so'')? Clearly, it'sbecause the implementation will put a 3.14 in the place where it passesdoubles, and then in the called function, try to pull an int from theplace where it passes ints. Now these may or may not be the same place, orthe same size, but even if they are the same place and the same size, thevalue received in i will obviously not be 3.14. Nor will it be <TT>(int)3.14</TT>,i.e. 3, because nothing in the code calls for a conversion.<p>If you declare the function with a prototype, the rules change:<p><pre> void fun2 (int i) { ... } main() { ... fun2 (3.14); ... }</pre><p>This is okay because the 3.14 is converted to int before being passed.The initial value of <TT>i</TT> will be 3.<p>Now consider<p><pre> void fun3 (int i) { ... } main() { void (*funp)(double); ... funp = (void (*)(double)) fun3; funp (3.14); ... }</pre><p>At the point where the call is made, the implementation is seeing a pointerto a function whose argument is double, and therefore it will cheerfullyput the 3.14 in the place where it passes doubles, without converting it.It DOESN'T KNOW at that point that that pointer-to-function was actuallyDERIVED FROM a function expecting a different type of argument. And so,this code will fail in just the same way as the first example.<p>And it makes no difference, of course, if the cast and the function calltake place in different functions:<p><pre> void fun4 (int i) { ... } void funq (void (*funp) (double)) { funp (3.14); } main() { ... funq ((void (*)(double)) fun4); ... }</pre><p>But now we have arrived at a form equivalent to the one that was beingasked about. <TT>funq()</TT> corresponds to <TT>qsort()</TT>, in that it expects an argumentwhich is a pointer to a function with a particular argument type. And hereit is being given a pointer derived from a function taking a differentargument type. Again, the code fails in the same way as the first example.<p>There is one difference between the above examples and the situation askedabout. In the examples, the types are <TT>int</TT> and <TT>double</TT>; in the <TT>qsort()</TT> case,they are two different pointer types.<p>Now it happens that on the most commonly used C implementations today,all pointer types have the same representation and are passed to functionsin the same way. This fact masks the bug: if the caller places a pointerof type <TT>struct gnu *</TT> into the place where pointers of that type are placed,and the called function looks at the place where pointers of type<TT>const void *</TT> are placed, and it's the same place and the two pointer types havethe same representation, then the code will work. On machines that don'twork that way, it won't work.<p>It's easy to write the code the right way in the first place -- see theFAQ list for examples. So do it right. Please. And maybe pass thisarticle on to the next person you see doing it wrong.<pre>-- Mark Brader "`char **' parameters are packaged in GREENmsb@sq.com envelopes and placed on the FIFTH shelf."SoftQuad Inc., Toronto -- Chris Torek</pre><p>This article is in the public domain.</body><!-- Mirrored from c-faq.com/lib/qsort.msb.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:03:00 GMT --></html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -