home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!sdrc!thor!scjones
- From: scjones@thor.sdrc.com (Larry Jones)
- Newsgroups: comp.lang.c
- Subject: Re: Help. (Unix C)
- Summary: qsort comparison functions
- Message-ID: <2223@sdrc.COM>
- Date: 5 Nov 92 16:20:27 GMT
- References: <2214@sdrc.COM> <Bx8Cw8.5tB@portal.hq.videocart.com>
- Sender: news@sdrc.COM
- Lines: 71
-
- In article <Bx8Cw8.5tB@portal.hq.videocart.com>, dfuller@portal.hq.videocart.com (Dave Fuller) writes:
- > scjones@thor.sdrc.com (Larry Jones) writes:
- > : An ANSI compiler will, quite properly, object to this code -- it is
- > : neither correct nor portable. The comparison function *must* be
- > : defined with two "void *" arguments (or "char *" if your compiler is
- > : too old to support "void *"); that's what qsort calls it with. Some
- > : implementations use the same representation for all pointer types and
- > : on those implementations you can misdefine the function and it will
- > : work, but this is not guaranteed and there are systems where it will
- > : fail.
- > :
- > First of all, i don't use an ANSI compiler except for about 20%
- > of my code (the declaration of the function should have helped on that).
-
- That's too bad -- using an ANSI compiler and prototypes can point out a
- lot of subtle errors (like this one) that aren't easily found otherwise.
-
- > But, even on an ANSI compiler this will work. void is used to take on
- > no predetermined meaning, or to actually mean return NOTHING from a
- > function if used as a declaration type. malloc returns void *, but it
- > won't complain if you dont cast the return value and assign it to a
- > char *. Also, the strcmp() function is used QUITE OFTEN in qsort.
- > look at the definition for it though strcmp(const char*,const char*)
- > it doesn't have void * declared as you say a routine that qsort calls
- > *must* have.
-
- When you assign a void * to another pointer type, there is a conversion
- that takes place, just like when you assign a float to an int. Neither
- requires a cast, but the data is converted from one type to another.
- Now, as I said, many systems use the same representation for all
- pointer types; on these systems you don't actually have to do anything
- to convert from one pointer type to another, just like you don't have
- to do anything to convert from a signed int to an unsigned int on a 2's
- complement system (but you DO have to do things on a 1's complement or
- sign/magnitude system).
-
- However, what we're talking about with qsort is not assignment where the
- compiler knows to apply the appropriate conversion. What we're talking
- about is calling a function with one type of argument but defining it
- with a different type of argument. This is like calling sqrt() with an
- int argument (and no prototype). The compiler doesn't know any better,
- so it goes ahead and passes an int, but sqrt() treats it like a double
- whose value is usually nothing like the value of the int, and you get
- back a garbage result. The same thing happens here: qsort() calls the
- comparison function a passes it two void * arguments, but your
- comparison function treats those arguments like structure pointers. If
- structure pointers happen to have the same representation as void
- pointers, it works; if not, you get garbage. The only difference
- between this and the sqrt() case is that int and double have different
- representations on most machines so that almost never works, but struct
- pointers and void pointers have the same representation on most machines
- so it usually does work.
-
- char * and void * are guaranteed to have the same representation, so you
- are guaranteed that you can get away with that error, but technically it
- is still an error: void * and char * are different types. Of course, if
- you don't have an ANSI compiler, you *can't* use void *, you have to use
- char *, so the guarantee allows existing programs to continue to work.
-
- > And if the code were not portable, it compiles and works on a non-ansi
- > compiler (and all of the ANSI ones i tried), so please take back the
- > part where you say the code is not correct. it is.
-
- The exact code you posted will, in fact, compile on an ANSI compiler
- without diagnostics, but only because you haven't given the compiler
- enough information to know it's wrong. Use prototypes and it will no
- longer compile. It's wrong.
- ----
- Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH 45150-2789 513-576-2070
- larry.jones@sdrc.com or ...uunet!sdrc!larry.jones
- These findings suggest a logical course of action. -- Calvin
-