Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!news.glorb.com!npeer02.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!border3.nntp.dca.giganews.com!Xl.tags.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!local2.nntp.dca.giganews.com!nntp.earthlink.com!news.earthlink.com.POSTED!not-for-mail NNTP-Posting-Date: Mon, 23 Jul 2012 21:40:31 -0500 Message-ID: <500E0B1B.653C@mindspring.com> Date: Mon, 23 Jul 2012 22:40:27 -0400 From: pete Reply-To: pfiland@mindspring.com Organization: PF X-Mailer: Mozilla 3.04Gold (WinNT; I) MIME-Version: 1.0 Newsgroups: comp.lang.c Subject: Re: qsort man page References: <89644623-7e1c-4f8b-9f4d-6443526f0f73@u2g2000yqj.googlegroups.com> <0.7b858dd95d3281469ee0.20120721225709BST.87boj893re.fsf@bsb.me.uk> <500B7D7F.7CA2@mindspring.com> <0.58ba0ee876bab752444c.20120722144128BST.871uk37w1j.fsf@bsb.me.uk> <500C31F3.518B@mindspring.com> <0.1f04de2e214d1e935a0b.20120722213623BST.87k3xv5y9k.fsf@bsb.me.uk> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 140 X-Usenet-Provider: http://www.giganews.com NNTP-Posting-Host: 4.156.228.78 X-Trace: sv3-nJWHRXz0mz7e9rtEykTkkJ5mvElLWbwRffZa8HgC+8ogFq0i9w/0FSDJAB2vBuVTuG2WTd4uP4ouy9X!TqC8qOJb8s5Edfu53PUhNCNu49hjRbXkZONrssKxQiB4CoPAhEza5+Hd4wzf5To4EvL1lFe4gIq2!0A/HkrlLow== X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 X-Original-Bytes: 5615 X-Received-Bytes: 5756 Xref: csiph.com comp.lang.c:23641 Ben Bacarisse wrote: > > pete writes: > > > Ben Bacarisse wrote: > >> > >> pete writes: > >> > >> > Ben Bacarisse wrote: > >> >> > >> >> Bill Cunningham writes: > >> > >> >> > #include > >> >> > #include > >> >> > #include > >> >> > static int > >> >> > cmpstringp(const void *p1, const void *p2) > >> >> > { > >> >> > /* The actual arguments to this function are "pointers to > >> >> > pointers to char", but strcmp(3) arguments are > >> >> > "pointers > >> >> > to char", hence the following cast plus dereference */ > >> >> > return strcmp(* (char * const *) p1, * (char * const *) p2); > >> >> > } > >> > > >> > I think that the way that the const keyword > >> > is used in the return statement, > >> > shows some confusion on the part of the author. > >> > > >> > It causes the result of the dereference > >> > in the strcmp function call, to be const qualified, > >> > which is neither required nor consistent > >> > with the parameters of strcmp > >> > being pointers to const qualified types. > >> > >> I am not so sure. The const that is there is a Good Const. > >> Omitting it might cause a warning > >> (gcc will oblige) about "casting away" const. > >> The question as to whether there should be another: > >> > >> *(const char *const *)p1 > >> > >> is not clear cut to me. > >> The cast, as written, is a correct reflection > >> of the object being sorted, > >> and there is some documentary merit in doing that > >> -- cast only to the type of the thing being sorted. > > > > There is no const in the type of the data being sorted. > > The array being sorted by cmpstringp in the example, > > is argv, which is an array of (char *) type elements. > > > > The const is introduced by the parameter type of cmpstringp. > > That level of const and pointer is removed by the *. maybe I should > have said "cast to a const pointer to the type thing being pointed to" > but it was all getting a bit wordy. > > You see my point, I hope. One level of pointer and const comes from > using qsort, all the rest comes from the type of thing being sorted. > > >> Your suggestion, to cast to the type needed by strcmp, > >> is not wrong but, in general, I would avoid it. > >> If you cast to the type of the actual data, > >> the compiler will warn you if this type is not suitable for the > >> call being made. In essence, you get a little more checking. > > > >> No big deal in this case because strcmp > >> takes "safer" arguments that > >> those being passed, but if I were forced to used some odd compare > >> function like > >> > >> int caseless_compare_that_alters_the_data(char *s1, char *s2); > >> > >> to sort an array of const char **, > >> my rule would show up a problem. > >> You cast to the type of the actual data, > >> and the call to this function will be flagged up as dangerous. I don't know. Maybe I am being wrongly influenced by the warnings generated by the compiler that I am using. When I rewrite and compile cmpstringp to do the type conversions through assignment to intermediate objects onstead of by casts, I get warnings when the intermediate objects are of the same type as the cast from the original version of cmpstringp, (char *const *). I don't get warnings when the intermediate objects are of type (const char **). /* BEGIN new.c */ #include int cmpstringp(const void *p1, const void *p2) { return strcmp(* (char * const *) p1, * (char * const *) p2); } int cmpstringp_2(const void *p1, const void *p2) { /* ** This function is OK */ const char **pp1; const char **pp2; pp1 = p1; pp2 = p2; return strcmp(*pp1, *pp2); } int cmpstringp_3(const void *p1, const void *p2) { /* ** This function generates warnings */ char *const *pp1; char *const *pp2; pp1 = p1; pp2 = p2; /* ** (35) : warning C4090: '=' : different 'const' qualifiers ** (36) : warning C4090: '=' : different 'const' qualifiers */ return strcmp(*pp1, *pp2); } /* END new.c */ -- pete