qsort man page

  • Follow


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);
}
0
Reply billcun1 (68) 7/21/2012 9:14:10 PM

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.
0
Reply ben.usenet (6515) 7/21/2012 9:57:09 PM


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&#39;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&#39;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&#39;m clear. THanks.
[snip]
0
Reply billcun1 (68) 7/22/2012 1:07:54 AM

Ben Bacarisse wrote:
> 
> 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);
> > }

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.

-- 
pete
0
Reply pfiland (6613) 7/22/2012 4:11:43 AM

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.
0
Reply ben.usenet (6515) 7/22/2012 1:41:28 PM

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.

> 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.


-- 
pete
0
Reply pfiland (6613) 7/22/2012 5:01:39 PM

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.
0
Reply ben.usenet (6515) 7/22/2012 8:36:23 PM

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.
0
Reply mstorkamp (72) 7/23/2012 1:49:41 PM

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"};
0
Reply ike8 (164) 7/23/2012 2:43:16 PM

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&#39;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


0
Reply billcun1 (68) 7/23/2012 5:44:55 PM

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
0
Reply billcun1 (68) 7/23/2012 8:16:01 PM

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;quot;};
> 
> Ok I see what your saying. I&#39;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;quot;};
> 
> Ok I see what your saying. I&#39;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?

0
Reply schwarz45 (77) 7/23/2012 8:29:15 PM

On Monday, July 23, 2012 4:29:15 PM UTC-4, Barry Schwarz wrote:
=20
> Since there are no pointers to pointers in the above code, why are you br=
inging it up as an additional confusion factor?

 Barry the answer your looking for you answered in your own question just "=
....bringing it up as an additional confusion factor." Actually this code to=
 me being char *name[]; looks equivalent to a char ** and a protoype of cha=
r ** would probably take char *name[];

B


0
Reply billcun1 (68) 7/23/2012 11:56:13 PM

Ben Bacarisse wrote:
> 
> 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.

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 <string.h>

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
0
Reply pfiland (6613) 7/24/2012 2:40:27 AM

Bill Cunningham wrote:
> 
> 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? 

Because the argument that qsort will pass to cmpstringp,
when qsort calls cmpstringp,
is a pointer to a pointer.

> This is confusing me also with the strcmp
> parameters which are cast as a pointer to pointer and dereferenced.

The argument that qsort will pass to cmpstringp,
when qsort calls cmpstringp,
is a pointer to a pointer.

> 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);
> }



-- 
pete
0
Reply pfiland (6613) 7/24/2012 3:34:09 AM

Ike Naar wrote:
> 
> 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"};

/* BEGIN new.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NMEMB(A)        (sizeof (A) / sizeof *(A))

int cmpstringp(const void *p1, const void *p2);

int 
main(void)
{
    size_t element;
    char *name[] = {"fred","suzy","mike","jennifer"};
    
    qsort(name, NMEMB(name), sizeof *name, cmpstringp);
    for (element = 0; element != NMEMB(name); ++element) {
        puts(name[element]);
    }
    return 0;
}

int
cmpstringp(const void *p1, const void *p2)
{
    const char *const *const pp1 = p1;
    const char *const *const pp2 = p2;

    return strcmp(*pp1, *pp2);
}

/* END new.c */

-- 
pete
0
Reply pfiland (6613) 7/24/2012 3:39:15 AM

pete wrote:
> 
> Bill Cunningham wrote:
> >
> > 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?
> 
> Because the argument that qsort will pass to cmpstringp,
> when qsort calls cmpstringp,
> is a pointer to a pointer.

The actual pointers passed by qsort could be of any type,
but the elements of the array being sorted are pointers,
and the pointers passed to cmpstringp from qsort,
will point to those pointer elements.

-- 
pete
0
Reply pfiland (6613) 7/24/2012 4:07:50 AM

In article <500E0B1B.653C@mindspring.com>,
pete  <pfiland@mindspring.com> wrote:
>
>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 *).

That's strange. The assignments aren't any worse than the cast. I think
they're slightly better because they're more constrained (the cast will
convert any pointer to any other pointer; the assignment requires compatible
types or void).

>
>I don't get warnings when the intermediate objects are 
>of type (const char **).
>
>
>/* BEGIN new.c */
>
>#include <string.h>
>
>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;

gcc warns here.
new.c: In function 'cmpstringp_2':
new.c:20: warning: assignment discards qualifiers from pointer target type
new.c:21: warning: assignment discards qualifiers from pointer target type

It didn't even need -Wall to produce those warnings. They're pretty severe.
And they're right. After the assignments, *pp1 = "oops" would be allowed
according to the type of pp1, but it's pointing to something that the caller
of the function didn't give you permission to modify.

>
>    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 */

gcc doesn't find anything wrong with cmpstringp_3 even with more warnings
enabled. Could you try your compiler with typedefs for the inner pointer?

typedef char *string;
typedef const char *fixedstring;

int
cmpstringp_4(const void *p1, const void *p2)
{
    fixedstring *pp1;
    fixedstring *pp2;

    pp1 = p1;
    pp2 = p2;

    return strcmp(*pp1, *pp2);
}

int
cmpstringp_5(const void *p1, const void *p2)
{
    const string *pp1;
    const string *pp2;

    pp1 = p1;
    pp2 = p2;
    return strcmp(*pp1, *pp2);
}

cmpstringp_4 and cmpstringp_5 should be exactly equivalent to cmpstringp_2
and cmpstringp_3 respectively, unless I messed up. gcc treats them the same.
Warnings on cmpstringp_4, none on cmpstringp_5.

0
Reply pacman5 (288) 7/24/2012 4:29:13 AM

Bill Cunningham wrote:

> [...] char *name[]; looks equivalent to a char ** and a protoype
> of char ** would probably take char *name[];

"Array of foo" and "pointer to foo" are only "equivalent"
when used as function parameters, because only then does
an array "decay" into a pointer to its first element.

In other contexts, arrays and pointers are NOT interchangeable!!

Take a look at the recent thread:
"Difference of extern short *x and extern short x[]?"
(Date: Tue, 17 Jul 2012 14:10:45 +0200)

0
Reply Noob 7/24/2012 7:29:02 AM

pacman@kosh.dhis.org (Alan Curry) writes:

> In article <500E0B1B.653C@mindspring.com>,
> pete  <pfiland@mindspring.com> wrote:
>>
>>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 *).
>
> That's strange.

I echo that.  gcc 4.6.3 gives the warnings for cmpstringp_2 as one would
expect and not for cmpstringp_3 (again as one would expect).

> The assignments aren't any worse than the cast. I think
> they're slightly better because they're more constrained (the cast will
> convert any pointer to any other pointer; the assignment requires compatible
> types or void).

With the extra flexibility (over plain compatibility) that:

  "the type pointed to by the left has all the qualifiers of the type
  pointed to by the right"

There should be a name for this -- maybe "assignment compatible".  It
applies to plain assignment and to argument passing which happens "as if
by assignment".

<snip>
-- 
Ben.
0
Reply ben.usenet (6515) 7/24/2012 10:40:09 AM

On Jul 21, 10:14=A0pm, Bill Cunningham <bill...@suddenlink.net> wrote:
> 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? =A0This is confusing me also with the strcmp
> parameters which are cast as a pointer to pointer and dereferenced. I
> hope I'm clear. THanks.

Just answer me this: Are you trolling, or are you just an incredibly
slow learner? I mean you have been posting questions of a confused
beginner for as far as I can remember.

Note: Any answer that you give, including none, will obviously answer
my question.
0
Reply christian.bau1 (402) 7/24/2012 11:36:01 PM

Ben Bacarisse wrote:
> 
> pacman@kosh.dhis.org (Alan Curry) writes:
> 
> > In article <500E0B1B.653C@mindspring.com>,
> > pete  <pfiland@mindspring.com> wrote:

> >>Maybe I am being wrongly influenced by the warnings
> >>generated by the compiler that I am using.

> > That's strange.
> 
> I echo that. 
> gcc 4.6.3 gives the warnings for cmpstringp_2 as one would
> expect and not for cmpstringp_3 (again as one would expect).

Thank you. 
It appears that I *have* 
been wrongly influenced by the compiler that I'm using.

-- 
pete
0
Reply pfiland (6613) 7/25/2012 2:06:21 AM

Noob <root@localhost> writes:
> Bill Cunningham wrote:
>
>> [...] char *name[]; looks equivalent to a char ** and a protoype
>> of char ** would probably take char *name[];
>
> "Array of foo" and "pointer to foo" are only "equivalent"
> when used as function parameters, because only then does
> an array "decay" into a pointer to its first element.

Incorrect.

There are actually two different things going on here.

An expression of array type is converted to a pointer to the array
object's first element in *most* contexts, not just when used as
a function argument (i.e., an expression in a function call).  The
exceptions are:

- When the array expression is the operand of a unary "&" operator
  (which yields the address of the entire array object, not the address
  of the address of the first element -- which wouldn't even make
  sense);
- When the array expression is the operand of a unary "sizeof" operator
  (which yields the size of the entire array, not the size of a pointer;
  and
- When the array expression is a string literal in an initializer, used
  to initialize an array object (for example,
      char s[6] = "hello";
  copies the entire array into s).

The other thing is that a function parameter defined as "array
of foo" is "adjusted" to a pointer to foo.  This is a compile-time
transformation, not a conversion.  Perhaps you were using the word
"decay" to refer to this adjustment, but that word is more often
used to refer to the conversion I described -- though the standard
doesn't use the word "decay", at least not in that sense.

These two rules conspire to make people *think* that arrays and pointers
are interchangeable.

See also, as always, section 6 of the comp.lang.c FAQ,
<http://www.c-faq.com/>.

> In other contexts, arrays and pointers are NOT interchangeable!!

Correct.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21474) 7/25/2012 6:17:14 AM

On Monday, July 23, 2012 6:56:13 PM UTC-5, Bill Cunningham wrote:
> On Monday, July 23, 2012 4:29:15 PM UTC-4, Barry Schwarz wrote:
> =20
> &gt; Since there are no pointers to pointers in the above code, why are y=
ou bringing it up as an additional confusion factor?
>=20
>  Barry the answer your looking for you answered in your own question just=
 &quot;...bringing it up as an additional confusion factor.&quot; Actually =
this code to me being char *name[]; looks equivalent to a char ** and a pro=
toype of char ** would probably take char *name[];

Your comments make no sense and add further support to the conclusion you j=
ust add things at random. =20

For the benefit of any newcomer reading this thread, the object definitions=
:

     char **x means x is a scalar object. =20

     char *y[5] means y is an aggregate object.

     parameter declarations in a function definition behave slightly differ=
ently due to special rules regarding arrays but that is a different topic.



0
Reply schwarz45 (77) 7/25/2012 4:51:10 PM

On Wednesday, July 25, 2012 12:51:10 PM UTC-4, Barry Schwarz wrote:
> On Monday, July 23, 2012 6:56:13 PM UTC-5, Bill Cunningham wrote:
> &gt; On Monday, July 23, 2012 4:29:15 PM UTC-4, Barry Schwarz wrote:
> &gt; =20
> &gt; &amp;gt; Since there are no pointers to pointers in the above code, =
why are you bringing it up as an additional confusion factor?
> &gt;=20
> &gt;  Barry the answer your looking for you answered in your own question=
 just &amp;quot;...bringing it up as an additional confusion factor.&amp;qu=
ot; Actually this code to me being char *name[]; looks equivalent to a char=
 ** and a protoype of char ** would probably take char *name[];
>=20
> Your comments make no sense and add further support to the conclusion you=
 just add things at random. =20
>=20
> For the benefit of any newcomer reading this thread, the object definitio=
ns:
>=20
>      char **x means x is a scalar object. =20
>=20
>      char *y[5] means y is an aggregate object.
>=20
>      parameter declarations in a function definition behave slightly diff=
erently due to special rules regarding arrays but that is a different topic=
..

Scalar or aggregate object? Huh? I'm not touching this one. This post isn't=
 addressed to me anyway it might be best just to abandon this thread.
0
Reply billcun1 (68) 7/26/2012 3:51:12 AM

On Jul 23, 1:44=A0pm, Bill Cunningham <bill...@suddenlink.net> wrote:
> 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&#39;t you post t=
he
> > 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 r=
ealize it was in November. Maybe I can look back and see what I got to work=
..
>
> Bill

I'd like to state for the fact of stating that I knew how to call
qsort() when I was 12 years old [18 something years ago...].  You're
not stupider than a 12 year old are you?

Tom
0
Reply tom236 (284) 7/26/2012 4:02:43 PM

In <84084cfa-8b5c-43e4-9f6d-cbbf5caf1ecd@u2g2000yqj.googlegroups.com> tom st denis <tom@iahu.ca> writes:

> I'd like to state for the fact of stating that I knew how to call
> qsort() when I was 12 years old [18 something years ago...].  You're
> not stupider than a 12 year old are you?

Some 12 year olds know how to milk a cow.

I don't know how to milk a cow, and I'd wager many of the folks in this
newsgroup don't either.

Does that make us stupider than a 12 year old?

-- 
John Gordon                   A is for Amy, who fell down the stairs
gordon@panix.com              B is for Basil, assaulted by bears
                                -- Edward Gorey, "The Gashlycrumb Tinies"

0
Reply gordon16 (619) 7/26/2012 4:41:04 PM

On Jul 26, 12:41=A0pm, John Gordon <gor...@panix.com> wrote:
> In <84084cfa-8b5c-43e4-9f6d-cbbf5caf1...@u2g2000yqj.googlegroups.com> tom=
 st denis <t...@iahu.ca> writes:
>
> > I'd like to state for the fact of stating that I knew how to call
> > qsort() when I was 12 years old [18 something years ago...]. =A0You're
> > not stupider than a 12 year old are you?
>
> Some 12 year olds know how to milk a cow.
>
> I don't know how to milk a cow, and I'd wager many of the folks in this
> newsgroup don't either.
>
> Does that make us stupider than a 12 year old?

If I spent 15 years trying to milk a cow and some 12 year old learned
how to do it in a weekend I might consider myself in need of help.

Tom
0
Reply tom236 (284) 7/26/2012 4:59:20 PM

On Wednesday, July 25, 2012 10:51:12 PM UTC-5, Bill Cunningham wrote:

> Scalar or aggregate object? Huh? I&#39;m not touching this one. This post isn&#39;t addressed to me anyway it might be best just to abandon this thread.

Thios is a Usenet discussion group.  Posts are not addressed to individuals at all.

If you are willing to abandon the thread without ever demonstrating that you have understood the answers to your original question, in fact just the opposite, one has to wonder why you bothered to ask in the first place.
0
Reply schwarz45 (77) 7/26/2012 9:27:57 PM

On Thursday, July 26, 2012 5:27:57 PM UTC-4, Barry Schwarz wrote:

> Thios is a Usenet discussion group.  Posts are not addressed to individuals at all.
> 
> If you are willing to abandon the thread without ever demonstrating that you have understood the answers to your original question, in fact just the opposite, one has to wonder why you bothered to ask in the first place.

I doubt that I could ever demonstrate to clc that I have the answers to the question even if I did. clc isn't exactly a learning group. Not enough patience. This is getting too technical. Doomed to failure. Thanks anyway.

0
Reply billcun1 (68) 7/27/2012 1:20:07 AM

On Thursday, July 26, 2012 8:20:07 PM UTC-5, Bill Cunningham wrote:
> On Thursday, July 26, 2012 5:27:57 PM UTC-4, Barry Schwarz wrote:
> 
> 
> 
> > Thios is a Usenet discussion group.  Posts are not addressed to individuals at all.
> 
> > 
> 
> > If you are willing to abandon the thread without ever demonstrating that you have understood the answers to your original question, in fact just the opposite, one has to wonder why you bothered to ask in the first place.
> 
> 
> 
> I doubt that I could ever demonstrate to clc that I have the answers to the question even if I did. clc isn't exactly a learning group. Not enough patience. This is getting too technical. Doomed to failure. Thanks anyway.

If you didn't want a technical answer, why are you posting to a newsgroup that deals with the technical aspects of the language?
0
Reply schwarz45 (77) 7/28/2012 2:24:34 PM

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> 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.   [snip]

It is a correct reflection of the object being _compared_.
It is not a correct reflection of the object being _sorted_,
which must be writable so it can be moved within the larger
array.
0
Reply txr1 (1213) 9/7/2012 6:38:23 PM

31 Replies
54 Views

(page loaded in 0.427 seconds)


Reply: