Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   qsort man page (http://www.velocityreviews.com/forums/t948368-qsort-man-page.html)

Bill Cunningham 07-21-2012 09:14 PM

qsort man page
 
This is from the qsort man page. I don't quite understand why there is
a comment here saying that arguments to this generic function to pass
to qsort is a pointer to pointer. It looks to me like cmpstringp takes
a generic pointer. Not pointer to pointer. Why does the comment say
pointer to pointer? This is confusing me also with the strcmp
parameters which are cast as a pointer to pointer and dereferenced. I
hope I'm clear. THanks.

Bill

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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);
}
int
main(int argc, char *argv[])
{
int j;
if (argc < 2) {
fprintf(stderr, "Usage: %s <string>...\n", argv[0]);
exit(EXIT_FAILURE);
}
qsort(&argv[1], argc - 1, sizeof(char *), cmpstringp);
for (j = 1; j < argc; j++)
puts(argv[j]);
exit(EXIT_SUCCESS);
}

Ben Bacarisse 07-21-2012 09:57 PM

Re: qsort man page
 
Bill Cunningham <billcun@suddenlink.net> writes:

> This is from the qsort man page. I don't quite understand why there is
> a comment here saying that arguments to this generic function to pass
> to qsort is a pointer to pointer. It looks to me like cmpstringp takes
> a generic pointer. Not pointer to pointer. Why does the comment say
> pointer to pointer?


Yup, cmpstringp takes two generic pointers, but in order to do anything
useful with them it must know to what kind of data they really point.
If the array being sorted is an array of ints, then the two pointers are
really pointing at int data, so casting to int * and dereferencing would
be the right thing to do (you'd write *(const int *)p1).

But, argv -- the array being sorted here -- is an array of character
pointers so the comparisson function gets passed pointers to a pair of
these character pointers, converted to "generic" (void *) pointers.

> This is confusing me also with the strcmp
> parameters which are cast as a pointer to pointer and dereferenced. I
> hope I'm clear. THanks.
>
> Bill
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 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);
> }
> int
> main(int argc, char *argv[])
> {
> int j;
> if (argc < 2) {
> fprintf(stderr, "Usage: %s <string>...\n", argv[0]);
> exit(EXIT_FAILURE);
> }
> qsort(&argv[1], argc - 1, sizeof(char *), cmpstringp);
> for (j = 1; j < argc; j++)
> puts(argv[j]);
> exit(EXIT_SUCCESS);
> }


--
Ben.

Bill Cunningham 07-22-2012 01:07 AM

Re: qsort man page
 
On Saturday, July 21, 2012 5:57:09 PM UTC-4, Ben Bacarisse wrote:
> Bill Cunningham &lt;billcun@suddenlink.net&gt; writes:
>
> &gt; This is from the qsort man page. I don't quite understand why there is
> &gt; a comment here saying that arguments to this generic function to pass
> &gt; to qsort is a pointer to pointer. It looks to me like cmpstringp takes
> &gt; a generic pointer. Not pointer to pointer. Why does the comment say
> &gt; pointer to pointer?
>
> Yup, cmpstringp takes two generic pointers, but in order to do anything
> useful with them it must know to what kind of data they really point.


I'm not quite sure I understand. I wanted to try this,

char name[]={"fred","suzy","mike","jennifer"};

And sort that using qsort. I know there are other functions that can be used with qsort like OT posix function but just speaking of C strcmp is the function to use.

Bill

> If the array being sorted is an array of ints, then the two pointers are
> really pointing at int data, so casting to int * and dereferencing would
> be the right thing to do (you'd write *(const int *)p1).
>
> But, argv -- the array being sorted here -- is an array of character
> pointers so the comparisson function gets passed pointers to a pair of
> these character pointers, converted to &quot;generic&quot; (void *) pointers.
>
> &gt; This is confusing me also with the strcmp
> &gt; parameters which are cast as a pointer to pointer and dereferenced. I
> &gt; hope I'm clear. THanks.

[snip]

Ben Bacarisse 07-22-2012 01:41 PM

Re: qsort man page
 
pete <pfiland@mindspring.com> writes:

> Ben Bacarisse wrote:
>>
>> Bill Cunningham <billcun@suddenlink.net> writes:

<snip>
>> > #include <stdio.h>
>> > #include <stdlib.h>
>> > #include <string.h>
>> > 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.

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.

--
Ben.

Ben Bacarisse 07-22-2012 08:36 PM

Re: qsort man page
 
pete <pfiland@mindspring.com> writes:

> Ben Bacarisse wrote:
>>
>> pete <pfiland@mindspring.com> writes:
>>
>> > Ben Bacarisse wrote:
>> >>
>> >> Bill Cunningham <billcun@suddenlink.net> writes:

>> <snip>
>> >> > #include <stdio.h>
>> >> > #include <stdlib.h>
>> >> > #include <string.h>
>> >> > 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.


--
Ben.

Mark Storkamp 07-23-2012 01:49 PM

Re: qsort man page
 
In article <b00418d1-e717-4207-99d4-0ac12f2accba@googlegroups.com>,
Bill Cunningham <billcun@suddenlink.net> wrote:

> On Saturday, July 21, 2012 5:57:09 PM UTC-4, Ben Bacarisse wrote:
> > Bill Cunningham &lt;billcun@suddenlink.net&gt; writes:


> I'm not quite sure I understand. I wanted to try this,
>
> char name[]={"fred","suzy","mike","jennifer"};
>
> And sort that using qsort. I know there are other functions that can be used
> with qsort like OT posix function but just speaking of C strcmp is the
> function to use.
>
> Bill


Last November you were trying to sort numbers. Why don't you post the
code you got to work from back then. Then maybe someone can show you
what needs to be changed to make it work for your char array.

Ike Naar 07-23-2012 02:43 PM

Re: qsort man page
 
On 2012-07-22, Bill Cunningham <billcun@suddenlink.net> wrote:
> I'm not quite sure I understand. I wanted to try this,
>
> char name[]={"fred","suzy","mike","jennifer"};


The types of the array and the initializer do not match.
You probably want

char *name[] = {"fred","suzy","mike","jennifer"};

Bill Cunningham 07-23-2012 05:44 PM

Re: qsort man page
 
On Monday, July 23, 2012 9:49:41 AM UTC-4, Mark Storkamp wrote:
> In article &lt;b00418d1-e717-4207-99d4-0ac12f2accba@googlegroups.com&gt;,


> Last November you were trying to sort numbers. Why don't you post the
> code you got to work from back then. Then maybe someone can show you
> what needs to be changed to make it work for your char array.


You have a very good memory. I remember asking about qsort but I didn't realize it was in November. Maybe I can look back and see what I got to work.

Bill



Bill Cunningham 07-23-2012 08:16 PM

Re: qsort man page
 
On Monday, July 23, 2012 10:43:16 AM UTC-4, Ike Naar wrote:

> The types of the array and the initializer do not match.
> You probably want
>
> char *name[] = {&quot;fred&quot;,&quot;suzy&quot;,&quot;mike&quot ;,&quot;jennifer&quot;};


Ok I see what your saying. I've never went as far as to get into pointers to pointers before.

B

Barry Schwarz 07-23-2012 08:29 PM

Re: qsort man page
 
On Monday, July 23, 2012 3:16:01 PM UTC-5, Bill Cunningham wrote:
> On Monday, July 23, 2012 10:43:16 AM UTC-4, Ike Naar wrote:
>
> &gt; The types of the array and the initializer do not match.
> &gt; You probably want
> &gt;
> &gt; char *name[] = {&amp;quot;fred&amp;quot;,&amp;quot;suzy&amp;quot; ,&amp;quot;mike&amp;quot;,&amp;quot;jennifer&amp;q uot;};
>
> Ok I see what your saying. I've never went as far as to get into pointers to pointers before.
>
> B




On Monday, July 23, 2012 3:16:01 PM UTC-5, Bill Cunningham wrote:
> On Monday, July 23, 2012 10:43:16 AM UTC-4, Ike Naar wrote:
>
> &gt; The types of the array and the initializer do not match.
> &gt; You probably want
> &gt;
> &gt; char *name[] = {&amp;quot;fred&amp;quot;,&amp;quot;suzy&amp;quot; ,&amp;quot;mike&amp;quot;,&amp;quot;jennifer&amp;q uot;};
>
> Ok I see what your saying. I've never went as far as to get into pointers to pointers before.


Since there are no pointers to pointers in the above code, why are you bringing it up as an additional confusion factor?



All times are GMT. The time now is 05:46 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.