A question about 13.9 from the c faq.

Discussion in 'C Programming' started by Chad, Dec 1, 2007.

  1. Chad

    Chad Guest

    At the following url http://c-faq.com/lib/qsort2.html, they have the
    following

    Q: Now I'm trying to sort an array of structures with qsort. My
    comparison function takes pointers to structures, but the compiler
    complains that the function is of the wrong type for qsort. How can I
    cast the function pointer to shut off the warning?

    A: The conversions must be in the comparison function, which must be
    declared as accepting ``generic pointers'' (const void *) as discussed
    in question 13.8 above. For a hypothetical little date structure

    struct mystruct {
    int year, month, day;
    };

    the comparison function might look like [footnote]

    int mystructcmp(const void *p1, const void *p2)
    {
    const struct mystruct *sp1 = p1;
    const struct mystruct *sp2 = p2;
    if(sp1->year < sp2->year) return -1;
    else if(sp1->year > sp2->year) return 1;
    else if(sp1->month < sp2->month) return -1;
    else if(sp1->month > sp2->month) return 1;
    else if(sp1->day < sp2->day) return -1;
    else if(sp1->day > sp2->day) return 1;
    else return 0;
    }

    (The conversions from generic pointers to struct mystruct pointers
    happen in the initializations sp1 = p1 and sp2 = p2; the compiler
    performs the conversions implicitly since p1 and p2 are void
    pointers.)

    The question is, why don't you use something like

    const struct mystruct *sp1 = &p1;
    const struct mystruct *sp2 = &p2;


    Chad
    Chad, Dec 1, 2007
    #1
    1. Advertising

  2. Chad

    Thad Smith Guest

    Chad wrote:

    > struct mystruct {
    > int year, month, day;
    > };
    >
    > the comparison function might look like [footnote]
    >
    > int mystructcmp(const void *p1, const void *p2)
    > {
    > const struct mystruct *sp1 = p1;
    > const struct mystruct *sp2 = p2;
    > if(sp1->year < sp2->year) return -1;
    > else if(sp1->year > sp2->year) return 1;
    > else if(sp1->month < sp2->month) return -1;
    > else if(sp1->month > sp2->month) return 1;
    > else if(sp1->day < sp2->day) return -1;
    > else if(sp1->day > sp2->day) return 1;
    > else return 0;
    > }
    >
    > The question is, why don't you use something like
    >
    > const struct mystruct *sp1 = &p1;
    > const struct mystruct *sp2 = &p2;


    The initializer would have the wrong type and value. You want to assign
    the pointer value, not the address of it.

    --
    Thad
    Thad Smith, Dec 1, 2007
    #2
    1. Advertising

  3. Chad

    Don Bruder Guest

    In article
    <>,
    Chad <> wrote:

    > At the following url http://c-faq.com/lib/qsort2.html, they have the
    > following
    >
    > Q: Now I'm trying to sort an array of structures with qsort. My
    > comparison function takes pointers to structures, but the compiler
    > complains that the function is of the wrong type for qsort. How can I
    > cast the function pointer to shut off the warning?
    >
    > A: The conversions must be in the comparison function, which must be
    > declared as accepting ``generic pointers'' (const void *) as discussed
    > in question 13.8 above. For a hypothetical little date structure
    >
    > struct mystruct {
    > int year, month, day;
    > };
    >
    > the comparison function might look like [footnote]
    >
    > int mystructcmp(const void *p1, const void *p2)
    > {
    > const struct mystruct *sp1 = p1;
    > const struct mystruct *sp2 = p2;
    > if(sp1->year < sp2->year) return -1;
    > else if(sp1->year > sp2->year) return 1;
    > else if(sp1->month < sp2->month) return -1;
    > else if(sp1->month > sp2->month) return 1;
    > else if(sp1->day < sp2->day) return -1;
    > else if(sp1->day > sp2->day) return 1;
    > else return 0;
    > }
    >
    > (The conversions from generic pointers to struct mystruct pointers
    > happen in the initializations sp1 = p1 and sp2 = p2; the compiler
    > performs the conversions implicitly since p1 and p2 are void
    > pointers.)
    >
    > The question is, why don't you use something like
    >
    > const struct mystruct *sp1 = &p1;
    > const struct mystruct *sp2 = &p2;


    Because:

    &p1 == the address of the variable (parameter, actually) p1

    p1 == the variable holding the address of the struct under comparison

    *p1 == the struct under comparison

    Assuming p1 contains the (randomly chosen) address 5, and assuming p1 is
    located in memory at (randomly chosen) location 27, and that the "..."
    is replaced by the "const struct mystruct *" as shown above, the
    following would be true:

    assignment result
    ....sp1 = &p1 sp now holds 27 (the address of p1)
    ....sp1 = p1 sp now holds 5 (the contents of p1)
    ....sp1 = *p1 sp now holds <whatever value is found at location 5>

    BUT...
    Since p1 is a function parameter, rather than an actual variable, I
    believe trying to take its address will result in undefined behavior.
    (unless special steps are taken to make things happen differently,
    parameters are usually passed on the stack, which makes taking their
    address either impossible, or pointless, because for practical purposes,
    they don't really HAVE an address to take.)

    --
    Don Bruder - - If your "From:" address isn't on my whitelist,
    or the subject of the message doesn't contain the exact text "PopperAndShadow"
    somewhere, any message sent to this address will go in the garbage without my
    ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
    Don Bruder, Dec 1, 2007
    #3
  4. Chad

    Eric Sosman Guest

    Chad wrote:
    > [... sorting arrays of structs with qsort() ...]
    >
    > struct mystruct {
    > int year, month, day;
    > };
    >
    > the comparison function might look like [footnote]
    >
    > int mystructcmp(const void *p1, const void *p2)
    > {
    > const struct mystruct *sp1 = p1;
    > const struct mystruct *sp2 = p2;
    > [...]
    >
    > The question is, why don't you use something like
    >
    > const struct mystruct *sp1 = &p1;
    > const struct mystruct *sp2 = &p2;


    Why don't you try it, and see what happens?

    To understand why <<spoiler alert>> the compiler complains,
    ask yourself: What is the type of `&p1'? And what does `&p1'
    point to? And to understand the FAQ's code, ask yourself:
    What does `p1' point to?

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 1, 2007
    #4
  5. Chad

    James Kuyper Guest

    Don Bruder wrote:
    ....
    > Since p1 is a function parameter, rather than an actual variable, I
    > believe trying to take its address will result in undefined behavior.


    A function parameter is an actual variable, and it's perfectly legal to
    take its address. The only problem is that it's the wrong address, in
    this context.

    > (unless special steps are taken to make things happen differently,
    > parameters are usually passed on the stack, which makes taking their
    > address either impossible, or pointless, because for practical purposes,
    > they don't really HAVE an address to take.)


    On the machines where I've had to be familiar with such details, the
    stack was a piece of memory that served a different purpose from the
    heap and other pieces of memory, but was just as addressable as any of
    those other pieces. If an implementation used something for parameter
    passing for which that wasn't true (such as registers), it must copy the
    values out of the registers into addressable memory, at least if the
    code ever actually takes the address of the parameter.
    James Kuyper, Dec 1, 2007
    #5
  6. Chad

    Chad Guest

    On Dec 1, 12:58 pm, Eric Sosman <> wrote:
    > Chad wrote:
    > > [... sorting arrays of structs with qsort() ...]

    >
    > > struct mystruct {
    > > int year, month, day;
    > > };

    >
    > > the comparison function might look like [footnote]

    >
    > > int mystructcmp(const void *p1, const void *p2)
    > > {
    > > const struct mystruct *sp1 = p1;
    > > const struct mystruct *sp2 = p2;
    > > [...]

    >
    > > The question is, why don't you use something like

    >
    > > const struct mystruct *sp1 = &p1;
    > > const struct mystruct *sp2 = &p2;

    >
    > Why don't you try it, and see what happens?
    >
    > To understand why <<spoiler alert>> the compiler complains,
    > ask yourself: What is the type of `&p1'? And what does `&p1'
    > point to? And to understand the FAQ's code, ask yourself:
    > What does `p1' point to?
    >
    > --
    > Eric Sosman
    >



    Maybe this is lack of experience or maybe it's because I will still
    once in a while get this burning sensation when I try to think, but it
    appears that p1 points to thing.
    Chad, Dec 1, 2007
    #6
  7. Chad

    Willem Guest

    James wrote:
    ) On the machines where I've had to be familiar with such details, the
    ) stack was a piece of memory that served a different purpose from the
    ) heap and other pieces of memory, but was just as addressable as any of
    ) those other pieces. If an implementation used something for parameter
    ) passing for which that wasn't true (such as registers), it must copy the
    ) values out of the registers into addressable memory, at least if the
    ) code ever actually takes the address of the parameter.

    Doesn't the standard allow an implementation that has a pointer type
    which can point to registers as well as memory ? I could imagine having
    some kind of 'fat' pointer type with a flag that indicates 'this is a
    pointer to register X'.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Dec 1, 2007
    #7
  8. Chad

    Don Bruder Guest

    In article <Iek4j.400$gi7.54@trnddc04>,
    James Kuyper <> wrote:

    > Don Bruder wrote:
    > ...
    > > Since p1 is a function parameter, rather than an actual variable, I
    > > believe trying to take its address will result in undefined behavior.

    >
    > A function parameter is an actual variable, and it's perfectly legal to
    > take its address.


    OK, then I've been operating under a misconception for a while. While
    they BEHAVE as variables, I've always been under the impression that
    they "weren't really" due to the passing mechanism.

    > The only problem is that it's the wrong address, in
    > this context.


    Right. The comparison would be against who-knows-what, but whatever that
    turned out to be, it wouldn't be the desired data.

    --
    Don Bruder - - If your "From:" address isn't on my whitelist,
    or the subject of the message doesn't contain the exact text "PopperAndShadow"
    somewhere, any message sent to this address will go in the garbage without my
    ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
    Don Bruder, Dec 1, 2007
    #8
  9. Chad

    Eric Sosman Guest

    Chad wrote:
    > On Dec 1, 12:58 pm, Eric Sosman <> wrote:
    >> Chad wrote:
    >>> [... sorting arrays of structs with qsort() ...]
    >>> struct mystruct {
    >>> int year, month, day;
    >>> };
    >>> the comparison function might look like [footnote]
    >>> int mystructcmp(const void *p1, const void *p2)
    >>> {
    >>> const struct mystruct *sp1 = p1;
    >>> const struct mystruct *sp2 = p2;
    >>> [...]
    >>> The question is, why don't you use something like
    >>> const struct mystruct *sp1 = &p1;
    >>> const struct mystruct *sp2 = &p2;

    >> Why don't you try it, and see what happens?
    >>
    >> To understand why <<spoiler alert>> the compiler complains,
    >> ask yourself: What is the type of `&p1'? And what does `&p1'
    >> point to? And to understand the FAQ's code, ask yourself:
    >> What does `p1' point to?

    >
    > Maybe this is lack of experience or maybe it's because I will still
    > once in a while get this burning sensation when I try to think, but it
    > appears that p1 points to thing.


    Right: `p1' points to one of the things in the array
    being sorted, that is, to a `struct mystruct' instance. The
    only problem is the type: `p1' is a `void*', but to get at
    the struct elements you need a `struct mystruct*'. Hence
    the conversion to `sp1'.

    How did you make out with the other two questions? (And
    did you try the experiment I suggested, or did you just accept
    my spoiler as Gospel? It's flattering when people believe
    what I say, but it's not always their wisest course ...)

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 1, 2007
    #9
  10. Chad <> writes:
    > At the following url http://c-faq.com/lib/qsort2.html, they have the
    > following
    >
    > Q: Now I'm trying to sort an array of structures with qsort. My
    > comparison function takes pointers to structures, but the compiler
    > complains that the function is of the wrong type for qsort. How can I
    > cast the function pointer to shut off the warning?
    >
    > A: The conversions must be in the comparison function, which must be
    > declared as accepting ``generic pointers'' (const void *) as discussed
    > in question 13.8 above. For a hypothetical little date structure
    >
    > struct mystruct {
    > int year, month, day;
    > };
    >
    > the comparison function might look like [footnote]
    >
    > int mystructcmp(const void *p1, const void *p2)
    > {
    > const struct mystruct *sp1 = p1;
    > const struct mystruct *sp2 = p2;
    > if(sp1->year < sp2->year) return -1;
    > else if(sp1->year > sp2->year) return 1;
    > else if(sp1->month < sp2->month) return -1;
    > else if(sp1->month > sp2->month) return 1;
    > else if(sp1->day < sp2->day) return -1;
    > else if(sp1->day > sp2->day) return 1;
    > else return 0;
    > }
    >
    > (The conversions from generic pointers to struct mystruct pointers
    > happen in the initializations sp1 = p1 and sp2 = p2; the compiler
    > performs the conversions implicitly since p1 and p2 are void
    > pointers.)
    >
    > The question is, why don't you use something like
    >
    > const struct mystruct *sp1 = &p1;
    > const struct mystruct *sp2 = &p2;


    Um, because it's illegal (a constraint violation), and even if it
    weren't it wouldn't work.

    p1 is a parameter (a local object) of type void* (I'm ignoring the
    const qualifier). When converted to type ``struct mystruct*'',
    assuming the caller has passed the right arguments, it points to an
    object of type ``struct mystruct''.

    You propose instead to use ``&p1'', i.e., the *address* of p1. This
    is the address of a pointer object, and is of type void**.

    The question is, why would you want to use ``&p1'' when ``p1'' is
    correct?

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 1, 2007
    #10
  11. Chad

    Chad Guest

    On Dec 1, 2:21 pm, Eric Sosman <> wrote:
    > Chad wrote:
    > > On Dec 1, 12:58 pm, Eric Sosman <> wrote:
    > >> Chad wrote:
    > >>> [... sorting arrays of structs with qsort() ...]
    > >>> struct mystruct {
    > >>> int year, month, day;
    > >>> };
    > >>> the comparison function might look like [footnote]
    > >>> int mystructcmp(const void *p1, const void *p2)
    > >>> {
    > >>> const struct mystruct *sp1 = p1;
    > >>> const struct mystruct *sp2 = p2;
    > >>> [...]
    > >>> The question is, why don't you use something like
    > >>> const struct mystruct *sp1 = &p1;
    > >>> const struct mystruct *sp2 = &p2;
    > >> Why don't you try it, and see what happens?

    >
    > >> To understand why <<spoiler alert>> the compiler complains,
    > >> ask yourself: What is the type of `&p1'? And what does `&p1'
    > >> point to? And to understand the FAQ's code, ask yourself:
    > >> What does `p1' point to?

    >
    > > Maybe this is lack of experience or maybe it's because I will still
    > > once in a while get this burning sensation when I try to think, but it
    > > appears that p1 points to thing.

    >
    > Right: `p1' points to one of the things in the array
    > being sorted, that is, to a `struct mystruct' instance. The
    > only problem is the type: `p1' is a `void*', but to get at
    > the struct elements you need a `struct mystruct*'. Hence
    > the conversion to `sp1'.
    >
    > How did you make out with the other two questions? (And
    > did you try the experiment I suggested, or did you just accept
    > my spoiler as Gospel? It's flattering when people believe
    > what I say, but it's not always their wisest course ...)
    >
    > --
    > Eric Sosman
    >



    The example in 13.9 as the same as the lines of code in a project that
    I'm working on. Anyhow, here is what happens when I take the address.

    int
    compare (const void *a, const void *b)
    {
    /*const struct utmp *ma = *(const struct utmp *const*)a;
    const struct utmp *mb = *(const struct utmp *const*)b;*/

    const struct utmp *ma = &a;
    const struct utmp *mb = &b;
    int32_t time1, time2;
    time1 = ma->ut_time;
    time2 = mb->ut_time;

    if(time1 < time2)
    return -1;
    else if(time1 > time2)
    return 1;
    else
    return 0;
    }


    % gcc -g no.c -o no -lkvm
    no.c: In function `compare':
    no.c:135: warning: initialization from incompatible pointer type
    no.c:136: warning: initialization from incompatible pointer type

    Without look at the disassembler, I would venture to say that a and b
    are of type (struct utmp)
    Chad, Dec 1, 2007
    #11
  12. Chad

    James Kuyper Guest

    Willem wrote:
    > James wrote:
    > ) On the machines where I've had to be familiar with such details, the
    > ) stack was a piece of memory that served a different purpose from the
    > ) heap and other pieces of memory, but was just as addressable as any of
    > ) those other pieces. If an implementation used something for parameter
    > ) passing for which that wasn't true (such as registers), it must copy the
    > ) values out of the registers into addressable memory, at least if the
    > ) code ever actually takes the address of the parameter.
    >
    > Doesn't the standard allow an implementation that has a pointer type
    > which can point to registers as well as memory ? I could imagine having
    > some kind of 'fat' pointer type with a flag that indicates 'this is a
    > pointer to register X'.


    Sure. I was talking about hypothetical implementations which passed
    arguments using non-addressable memory; an implementation such as you
    describe wouldn't qualify.
    James Kuyper, Dec 1, 2007
    #12
  13. Chad

    James Kuyper Guest

    Chad wrote:
    ....
    > int
    > compare (const void *a, const void *b)
    > {
    > /*const struct utmp *ma = *(const struct utmp *const*)a;
    > const struct utmp *mb = *(const struct utmp *const*)b;*/
    >
    > const struct utmp *ma = &a;
    > const struct utmp *mb = &b;
    > int32_t time1, time2;
    > time1 = ma->ut_time;
    > time2 = mb->ut_time;
    >
    > if(time1 < time2)
    > return -1;
    > else if(time1 > time2)
    > return 1;
    > else
    > return 0;
    > }
    >
    >
    > % gcc -g no.c -o no -lkvm
    > no.c: In function `compare':
    > no.c:135: warning: initialization from incompatible pointer type
    > no.c:136: warning: initialization from incompatible pointer type
    >
    > Without look at the disassembler, I would venture to say that a and b
    > are of type (struct utmp)


    Both a and b are declared as pointers to void. Neither one has the type
    (struct utmp). When compare() is called by qsort() to compare two struct
    utmp objects, then a and b will each point at the positions in memory
    containing those objects. However, they don't have the correct type to
    be used to directly access those structs. Both ma and mb have the
    correct type to be used for accessing a struct utmp, but they can only
    be used that way if correctly initialized.

    If you had initialized ma with the converted value of a, it would have
    been correct. However, you used "&a". The value of that expression is a
    pointer which points at the object named 'a'. That object is in a
    completely different piece of memory than the piece of memory that 'a'
    points at.

    There is something wrong about the way you're thinking about this, but
    I'm not quite sure what it is.
    James Kuyper, Dec 1, 2007
    #13
  14. Chad

    Guest

    On Dec 2, 6:26 am, Keith Thompson <> wrote:
    > Chad <> writes:
    > > At the following urlhttp://c-faq.com/lib/qsort2.html, they have the
    > > following

    >
    > > Q: Now I'm trying to sort an array of structures with qsort. My
    > > comparison function takes pointers to structures, but the compiler
    > > complains that the function is of the wrong type for qsort. How can I
    > > cast the function pointer to shut off the warning?

    >
    > > A: The conversions must be in the comparison function, which must be
    > > declared as accepting ``generic pointers'' (const void *) as discussed
    > > in question 13.8 above. For a hypothetical little date structure

    >
    > > struct mystruct {
    > > int year, month, day;
    > > };

    >
    > > the comparison function might look like [footnote]

    >
    > > int mystructcmp(const void *p1, const void *p2)
    > > {
    > > const struct mystruct *sp1 = p1;
    > > const struct mystruct *sp2 = p2;
    > > if(sp1->year < sp2->year) return -1;
    > > else if(sp1->year > sp2->year) return 1;
    > > else if(sp1->month < sp2->month) return -1;
    > > else if(sp1->month > sp2->month) return 1;
    > > else if(sp1->day < sp2->day) return -1;
    > > else if(sp1->day > sp2->day) return 1;
    > > else return 0;
    > > }

    >
    > > (The conversions from generic pointers to struct mystruct pointers
    > > happen in the initializations sp1 = p1 and sp2 = p2; the compiler
    > > performs the conversions implicitly since p1 and p2 are void
    > > pointers.)

    >
    > > The question is, why don't you use something like

    >
    > > const struct mystruct *sp1 = &p1;
    > > const struct mystruct *sp2 = &p2;

    >
    > Um, because it's illegal (a constraint violation), and even if it
    > weren't it wouldn't work.
    >
    > p1 is a parameter (a local object) of type void* (I'm ignoring the
    > const qualifier). When converted to type ``struct mystruct*'',
    > assuming the caller has passed the right arguments, it points to an
    > object of type ``struct mystruct''.
    >
    > You propose instead to use ``&p1'', i.e., the *address* of p1. This
    > is the address of a pointer object, and is of type void**.
    >


    Does the operation &expr yield value of void* type? Is void* the
    default data type for pointers. I ever heard that there is not a data
    type called `pointer type', but there are `pointer types' of pointers
    pointed to data of some kinds of types.
    , Dec 2, 2007
    #14
  15. Chad

    Willem Guest

    wrote:
    ) Does the operation &expr yield value of void* type?

    No.

    ) Is void* the default data type for pointers.

    No.

    ) I ever heard that there is not a data type called `pointer type', but
    ) there are `pointer types' of pointers pointed to data of some kinds of
    ) types.

    Almost.
    There are 'pointer types' of pointers to data of _all_ kinds of types.
    Even to pointer types. Even to pointer types pointing to pointer types.
    Etcetera.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
    Willem, Dec 2, 2007
    #15
  16. "" <> writes:
    [...]
    > Does the operation &expr yield value of void* type? Is void* the
    > default data type for pointers. I ever heard that there is not a data
    > type called `pointer type', but there are `pointer types' of pointers
    > pointed to data of some kinds of types.


    Do you have a C textbook?

    No, the "&" operator does not yield a result of type void*. "&expr"
    is of type "pointer to FOO", where "FOO" is the type of the expression
    (which must be an lvalue).

    There is no "default data type for pointers". void* is a generic
    pointer type, in the sense that (a) a value of any pointer-to-object
    type or pointer-to-incomplete type can be implicitly converted to
    void* or vice versa, and (b) converting a pointer value to void* and
    back again is guaranteed to yield the orginial value.

    For each data type, there is a distinct pointer type that points to
    objects of that data type.

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 2, 2007
    #16
  17. Chad

    Paul Sinnett Guest

    Chad wrote:
    > int
    > compare (const void *a, const void *b)


    ....

    > Without look at the disassembler, I would venture to say that a and b
    > are of type (struct utmp)


    No, a and b as you've declared them are of type "pointer to void." You
    can think of this as a pointer to something you don't know about.

    To make them into pointers to something you want, you have to cast them.
    And you cast them from type "pointer to void" to "pointer to utmp".

    Since you're casting from one type of pointer to another, you shouldn't
    try to take the address with &a. If you use &a you will get the address
    of a pointer, not the address of the utmp structure you are after.
    Paul Sinnett, Dec 2, 2007
    #17
  18. Chad

    pete Guest

    Don Bruder wrote:
    >
    > In article <Iek4j.400$gi7.54@trnddc04>,
    > James Kuyper <> wrote:


    > > A function parameter is an actual variable,
    > > and it's perfectly legal to take its address.

    >
    > OK, then I've been operating under a misconception for a while. While
    > they BEHAVE as variables, I've always been under the impression that
    > they "weren't really" due to the passing mechanism.


    Parameters are local objects in function definitions.
    Parameters are initialised
    by the values of arguments in function calls.

    --
    pete
    pete, Dec 2, 2007
    #18
  19. Chad

    Thad Smith Guest

    Don Bruder wrote:
    > In article
    > <>,
    > Chad <> wrote:


    >> struct mystruct {
    >> int year, month, day;
    >> };
    >>
    >> the comparison function might look like [footnote]
    >>
    >> int mystructcmp(const void *p1, const void *p2)
    >> {
    >> const struct mystruct *sp1 = p1;
    >> const struct mystruct *sp2 = p2;
    >> if(sp1->year < sp2->year) return -1;
    >> else if(sp1->year > sp2->year) return 1;
    >> else if(sp1->month < sp2->month) return -1;
    >> else if(sp1->month > sp2->month) return 1;
    >> else if(sp1->day < sp2->day) return -1;
    >> else if(sp1->day > sp2->day) return 1;
    >> else return 0;
    >> }
    >>...
    >> The question is, why don't you use something like
    >>
    >> const struct mystruct *sp1 = &p1;
    >> const struct mystruct *sp2 = &p2;

    >
    > Because:
    >
    > &p1 == the address of the variable (parameter, actually) p1
    >
    > p1 == the variable holding the address of the struct under comparison
    >
    > *p1 == the struct under comparison
    >
    > Assuming p1 contains the (randomly chosen) address 5, and assuming p1 is
    > located in memory at (randomly chosen) location 27, and that the "..."
    > is replaced by the "const struct mystruct *" as shown above, the
    > following would be true:
    >
    > assignment result
    > ...sp1 = &p1 sp now holds 27 (the address of p1)
    > ...sp1 = p1 sp now holds 5 (the contents of p1)
    > ...sp1 = *p1 sp now holds <whatever value is found at location 5>


    This approach works well for me and I encourage others to use it by
    "playing computer" and assign sample values for variables. While
    pointers aren't necessarily simple addresses, I use addresses for
    examples because addresses are
    1) a simple model which can help understanding
    2) accurate description for many implementations.

    Since I can't keep much in my head without it turning to soup, I write
    down sample values. Here is an example for the comparison function:

    Let's assume that ints are 4 bytes each and that pointers are addresses
    of memory. Assume, for this example, that there is a declaration

    struct mystruct ms[5] = {{1812,1,1}, <more initializations> };

    to allocate the array to be sorted and that ms has the address 1000.
    Assume that struct mystruct has no padding, so sizeof (ms[0]) = 12.
    Assume further that mystructcmp was called to compare ms[0] and ms[1].
    Assume that parameters p1 and p2 have the address 2000 and 2004 and sp1
    has the address 3000.

    Variable Address Value Type
    ms[0] 1000 struct mystruct
    ms[0].year 1000 1812 int
    ms[1] 1012
    ms[4] 1048
    p1 2000 1000 const void*
    p2 2004 1012 const void*

    If we initialize sp1 by
    const struct mystruct *sp1 = p1;

    we get

    sp1 3000 1000 const struct mystruct *

    Then when we access sp1->year, the offset 0 is added to 1000, the value
    of the pointer, and we read address 1000, giving the int value 1812,
    which is ms[0].year, exactly what we want.

    If, instead, sp1 is initialized by
    const struct mystruct *sp1 = &p1;

    we get

    sp1 3000 2000 const struct mystruct *

    When the code accesses sp1->year, it reads the contents of 2000, giving
    the value 1000, which is an address, not the intended value of 1812.

    In general, things get a lot worse when using the wrong pointer value,
    including attempting to read addresses that aren't even assigned to the
    program.

    Playing computer with sample values, writing down results as statements
    are executed, helps me to see whether the declarations and logic makes
    sense. I do this when I am using pointers a lot, such as working with
    linked lists, but also works well with other computation.

    --
    Thad
    Thad Smith, Dec 2, 2007
    #19
  20. Chad

    Default User Guest

    Keith Thompson wrote:

    > "" <> writes:
    > [...]
    > > Does the operation &expr yield value of void* type?


    > Do you have a C textbook?


    Why in the world does anyone respond to this guy anymore?




    Brian
    Default User, Dec 3, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Philip Lawatsch
    Replies:
    9
    Views:
    770
    tom_usenet
    Jul 9, 2003
  2. =?ISO-8859-15?Q?Juli=E1n?= Albo

    FAQ or not FAQ?

    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jan 8, 2007, in forum: C++
    Replies:
    28
    Views:
    851
    Grizlyk
    Jan 15, 2007
  3. Josef 'Jupp' Schugt
    Replies:
    0
    Views:
    191
    Josef 'Jupp' Schugt
    Sep 22, 2003
  4. FAQ server

    FAQ - How do I direct someone to this FAQ?

    FAQ server, Aug 4, 2006, in forum: Javascript
    Replies:
    1
    Views:
    150
    Dr John Stockton
    Aug 4, 2006
  5. Peter Michaux

    FAQ/FAQ notes site makeover

    Peter Michaux, Nov 22, 2006, in forum: Javascript
    Replies:
    22
    Views:
    343
    Randy Webb
    Nov 27, 2006
Loading...

Share This Page