martin@mwtech.UUCP (Martin Weitzel) (05/23/91)
There has recently been some discussion about the correct way to write comparison functions for qsort. (I've seen it as well in the CUJ as also in a local German group). There seems to be some consensus that the comparison function must be written expecting two pointers to void and eventually casting (or assigning) them internally to the required pointer type. Taking into consideration that the number and types of function parameters for any function determines the calling sequence and further considering that qsort already makes a call to the comparison function (via the function pointer) and hence has a certain calling sequence compiled in, this all seems reasonable to me. (By "calling sequence" I mean the details how parameters are transferred to the function from the place where the function is called and how the parameters are accessed from inside the function. Of course, both ways must match.) But have a look at the example in K&R-II, page 119-120 and the explanations that accompany it - isn't it, say, at least a bit misleading, or, may be, even wrong? (Oh boy, was this hard to type in now, suspecting the fathers of C to have written something that might be wrong.) The point in question is the cast of the comparison function pointer when handed as parameter to qsort and the explanation for the cast: "The elaborate cast of the function argument casts the arguments of the comparison function. These will generally have no effect on actual representation but assure the compiler that all is well." First, IMHO the cast they apply has not the least effect on the ARGUMENTS of the COMPARISION function; Second, IMHO ANSI C even GUARANTEES that the cast has no effect on the REPRESENTATION, since all function pointers have the same representation and pointers to char have the same representation as pointers to void. (This second point would really be of minor importance - basically it centers on whether one could omit "generally" from the last sentence above. As this sentence could be seen to refer also to the sentence immediately before the one with which I started my citation, one could even argue that the "generally" justified. But I mention it because I think it points the naive reader into quite a wrong direction.) Third and most important: Will the guarantees ANSI C gives with respect to the (identical) representation of certain pointer types extend to the calling sequence of a function? Or, in the context of the above example: Does the identical representation of pointers to char and pointers to void extend to an identical calling sequence for |int f1(void *, void *)| and |int f2(char *, char *)| ? If not, the example in K&R-II is not guaranteed to work! -- Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83