const type question

Discussion in 'C Programming' started by herrcho, Oct 3, 2003.

  1. herrcho

    herrcho Guest

    int intcmp(const void *a, const void *b)
    {
    return (*(int*)a - *(int*)b);
    }

    in the above , if i put just 'void' instead of 'const void' as a
    parameter,

    what's the difference ?

    i can't get the meaning of const when used in parameter..

    Thanks in advance ~
     
    herrcho, Oct 3, 2003
    #1
    1. Advertising

  2. herrcho

    Richard Bos Guest

    "herrcho" <> wrote:

    > int intcmp(const void *a, const void *b)
    > {
    > return (*(int*)a - *(int*)b);
    > }
    >
    > in the above , if i put just 'void' instead of 'const void' as a
    > parameter,
    >
    > what's the difference ?


    Nothing, since you're not trying to change anything anyway.

    > i can't get the meaning of const when used in parameter..


    If a parameter is declared const, the function cannot change it. This
    sounds like it's no change, since a function cannot change a the value
    of a parameter in the caller anyway. However, if the parameter is const,
    the function cannot even change its value _within the function_.
    If a parameter is a pointer to a const type, the function cannot change
    the object the pointer points at.

    If you don't modify anything in the function to begin with, this doesn't
    matter, of course. However, the above looks like a comparison function
    for qsort() (or bsearch()). In that case, the consts are there to
    prevent you from changing the objects behind qsort()'s back, since doing
    so could mess up the sorting algorithm.

    Richard
     
    Richard Bos, Oct 3, 2003
    #2
    1. Advertising

  3. herrcho

    Simon Biber Guest

    "herrcho" <> wrote:
    > int intcmp(const void *a, const void *b)
    > {
    > return (*(int*)a - *(int*)b);
    > }
    >
    > in the above , if i put just 'void' instead of 'const void' as a
    > parameter,
    >
    > what's the difference ?


    If you're intending to pass this function to qsort or something
    that expects a parameter of type int(*)(const void*,const void*)
    then you must not change from const void to void, this will be
    a constraint violation (wrong type of argument) or else undefined
    behaviour (if you say cast it back to the right type).

    > i can't get the meaning of const when used in parameter..


    When used as 'const type *a' it means that you are not allowed to
    modify the thing that the pointer is pointing to. Unfortunately
    due to the bad way you wrote the function this protection is lost
    when you cast the argument to (int*). You can in fact write any
    qsort compare function in a completely typesafe manner with no
    casts, which is much cleaner code:

    int intcmp(const void *va, const void *vb)
    {
    const int *a = va, *b = vb;
    return *a - *b;
    }

    That way you will get a diagnostic message from the compiler if
    you accidentally attempt to modify the contents of the memory.

    --
    Simon.
     
    Simon Biber, Oct 3, 2003
    #3
  4. herrcho

    CBFalconer Guest

    Simon Biber wrote:
    >

    .... snip ...
    >
    > When used as 'const type *a' it means that you are not allowed to
    > modify the thing that the pointer is pointing to. Unfortunately
    > due to the bad way you wrote the function this protection is lost
    > when you cast the argument to (int*). You can in fact write any
    > qsort compare function in a completely typesafe manner with no
    > casts, which is much cleaner code:
    >
    > int intcmp(const void *va, const void *vb)
    > {
    > const int *a = va, *b = vb;
    > return *a - *b;
    > }
    >
    > That way you will get a diagnostic message from the compiler if
    > you accidentally attempt to modify the contents of the memory.


    Totally agree, EXCEPT for the actual comparison in your example,
    which is liable to problems from integer overflow. This is a good
    place for:

    return (*a > *b) - (*a < *b);

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Oct 3, 2003
    #4
  5. herrcho

    Simon Biber Guest

    "CBFalconer" <> wrote:
    > Simon Biber wrote:
    > > int intcmp(const void *va, const void *vb)
    > > {
    > > const int *a = va, *b = vb;
    > > return *a - *b;
    > > }
    > >
    > > That way you will get a diagnostic message from the compiler if
    > > you accidentally attempt to modify the contents of the memory.

    >
    > Totally agree, EXCEPT for the actual comparison in your example,
    > which is liable to problems from integer overflow. This is a good
    > place for:
    >
    > return (*a > *b) - (*a < *b);


    Yes, my mistake. In fact I usually write it like the equivalent:
    return (*a < *b) ? -1 : (*a > *b);

    But I prefer your subtraction form, because in the rather arbitrary
    and unjustified model of code microefficiency in my head, a subtract
    is faster than a compare. This may or may not be true on any of the
    platforms I compile for, I wouldn't know.

    --
    Simon.
     
    Simon Biber, Oct 3, 2003
    #5
  6. "Simon Biber" <> wrote in message
    news:3f7d8e5d$0$26924$...
    > You can in fact write any
    > qsort compare function in a completely typesafe manner


    How? The function itself can never guarantee that it won't be applied to a
    type that differs from the intended one.

    > with no casts, which is much cleaner code:


    Cleaner perhaps, but an absense of casts is not typesafety.

    --
    Peter
     
    Peter Nilsson, Oct 4, 2003
    #6
  7. herrcho

    pete Guest

    Simon Biber wrote:
    >
    > "CBFalconer" <> wrote:
    > > Simon Biber wrote:
    > > > int intcmp(const void *va, const void *vb)
    > > > {
    > > > const int *a = va, *b = vb;
    > > > return *a - *b;
    > > > }
    > > >
    > > > That way you will get a diagnostic message from the compiler if
    > > > you accidentally attempt to modify the contents of the memory.

    > >
    > > Totally agree, EXCEPT for the actual comparison in your example,
    > > which is liable to problems from integer overflow. This is a good
    > > place for:
    > >
    > > return (*a > *b) - (*a < *b);

    >
    > Yes, my mistake. In fact I usually write it like the equivalent:
    > return (*a < *b) ? -1 : (*a > *b);
    >
    > But I prefer your subtraction form, because in the rather arbitrary
    > and unjustified model of code microefficiency in my head, a subtract
    > is faster than a compare. This may or may not be true on any of the
    > platforms I compile for, I wouldn't know.


    I see two unconditional comparisons and a subtraction
    in the first,
    but only two comparisons, with one of them being conditional,
    in the second.

    --
    pete
     
    pete, Oct 4, 2003
    #7
  8. herrcho

    CBFalconer Guest

    pete wrote:
    > Simon Biber wrote:
    > > "CBFalconer" <> wrote:
    > > > Simon Biber wrote:

    > >
    > > > > int intcmp(const void *va, const void *vb)
    > > > > {
    > > > > const int *a = va, *b = vb;
    > > > > return *a - *b;
    > > > > }
    > > > >
    > > > > That way you will get a diagnostic message from the compiler if
    > > > > you accidentally attempt to modify the contents of the memory.
    > > >
    > > > Totally agree, EXCEPT for the actual comparison in your example,
    > > > which is liable to problems from integer overflow. This is a good
    > > > place for:
    > > >
    > > > return (*a > *b) - (*a < *b);

    > >
    > > Yes, my mistake. In fact I usually write it like the equivalent:
    > > return (*a < *b) ? -1 : (*a > *b);
    > >
    > > But I prefer your subtraction form, because in the rather arbitrary
    > > and unjustified model of code microefficiency in my head, a subtract
    > > is faster than a compare. This may or may not be true on any of the
    > > platforms I compile for, I wouldn't know.

    >
    > I see two unconditional comparisons and a subtraction in the first,
    > but only two comparisons, with one of them being conditional,
    > in the second.


    However the emitted code will often not have any jumps in it (for
    the first), which avoids flushing any instruction queues. I
    learned it from someone, and consider it a trick worth knowing.

    The point is that they are both safe, and have a chance to
    simultaneously be efficient and clear. However there may be
    considerable code involved in converting a machine comparison into
    the 0 or 1 representation, in which case the ?: coding will be
    superior.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Oct 4, 2003
    #8
  9. herrcho

    pete Guest

    CBFalconer wrote:
    >
    > pete wrote:
    > > Simon Biber wrote:
    > > > "CBFalconer" <> wrote:
    > > > > Simon Biber wrote:
    > > >
    > > > > > int intcmp(const void *va, const void *vb)
    > > > > > {
    > > > > > const int *a = va, *b = vb;
    > > > > > return *a - *b;
    > > > > > }
    > > > > >
    > > > > > That way you will get a diagnostic message from the compiler if
    > > > > > you accidentally attempt to modify the contents of the memory.
    > > > >
    > > > > Totally agree, EXCEPT for the actual comparison in your example,
    > > > > which is liable to problems from integer overflow. This is a good
    > > > > place for:
    > > > >
    > > > > return (*a > *b) - (*a < *b);
    > > >
    > > > Yes, my mistake. In fact I usually write it like the equivalent:
    > > > return (*a < *b) ? -1 : (*a > *b);
    > > >
    > > > But I prefer your subtraction form,
    > > > because in the rather arbitrary
    > > > and unjustified model of code microefficiency in my head,
    > > > a subtract is faster than a compare.
    > > > This may or may not be true on any of the
    > > > platforms I compile for, I wouldn't know.

    > >
    > > I see two unconditional comparisons and a subtraction in the first,
    > > but only two comparisons, with one of them being conditional,
    > > in the second.

    >
    > However the emitted code will often not have any jumps in it (for
    > the first), which avoids flushing any instruction queues. I
    > learned it from someone, and consider it a trick worth knowing.
    >
    > The point is that they are both safe, and have a chance to
    > simultaneously be efficient and clear. However there may be
    > considerable code involved in converting a machine comparison into
    > the 0 or 1 representation, in which case the ?: coding will be
    > superior.


    Thank you.

    --
    pete
     
    pete, Oct 4, 2003
    #9
  10. herrcho

    Guest

    "Simon Biber" <> wrote in message news:<3f7d8e5d$0$26924$>...
    > "herrcho" <> wrote:
    > > int intcmp(const void *a, const void *b)
    > > {
    > > return (*(int*)a - *(int*)b);
    > > }
    > >
    > > in the above , if i put just 'void' instead of 'const void' as a
    > > parameter,
    > >
    > > what's the difference ?

    >
    > If you're intending to pass this function to qsort or something
    > that expects a parameter of type int(*)(const void*,const void*)
    > then you must not change from const void to void, this will be
    > a constraint violation (wrong type of argument) or else undefined
    > behaviour (if you say cast it back to the right type).
    >
    > > i can't get the meaning of const when used in parameter..

    >
    > When used as 'const type *a' it means that you are not allowed to
    > modify the thing that the pointer is pointing to. Unfortunately
    > due to the bad way you wrote the function this protection is lost
    > when you cast the argument to (int*). You can in fact write any
    > qsort compare function in a completely typesafe manner with no
    > casts, which is much cleaner code:
    >
    > int intcmp(const void *va, const void *vb)
    > {
    > const int *a = va, *b = vb;
    > return *a - *b;
    > }
    >

    Friends,
    Don't we have to cast a void* so that the void points to a valid
    value (as per 6.3.2.3 of the standard). (Correct me if I am wrong):

    int fun(const void *a, const void *b)
    {
    unsigned int *p , *q;
    p =(unsigned int*) a, q =(unsigned int*) b;
    /*return (*p > *q ) - (*p < *q); */
    return *p - *q;
    }
    int main(void)
    {
    int a=2,b=2,c=8,d=6;
    printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    return 0;
    }

    OUTPUT:

    0 2

    And for the second one:

    int fun(const void *a, const void *b)
    {
    unsigned int *p , *q;
    p =(unsigned int*) a, q =(unsigned int*) b;
    return (*p > *q ) - (*p < *q);
    /*return *p - *q; */
    }
    int main(void)
    {
    int a=2,b=2,c=8,d=6;
    printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    return 0;
    }

    OUTPUT:
    0 1

    Is there any UB?




    > That way you will get a diagnostic message from the compiler if
    > you accidentally attempt to modify the contents of the memory.
     
    , Oct 4, 2003
    #10
  11. herrcho

    j Guest

    <> wrote in message
    news:...
    > "Simon Biber" <> wrote in message

    news:<3f7d8e5d$0$26924$>...
    > > "herrcho" <> wrote:
    > > > int intcmp(const void *a, const void *b)
    > > > {
    > > > return (*(int*)a - *(int*)b);
    > > > }
    > > >
    > > > in the above , if i put just 'void' instead of 'const void' as a
    > > > parameter,
    > > >
    > > > what's the difference ?

    > >
    > > If you're intending to pass this function to qsort or something
    > > that expects a parameter of type int(*)(const void*,const void*)
    > > then you must not change from const void to void, this will be
    > > a constraint violation (wrong type of argument) or else undefined
    > > behaviour (if you say cast it back to the right type).
    > >
    > > > i can't get the meaning of const when used in parameter..

    > >
    > > When used as 'const type *a' it means that you are not allowed to
    > > modify the thing that the pointer is pointing to. Unfortunately
    > > due to the bad way you wrote the function this protection is lost
    > > when you cast the argument to (int*). You can in fact write any
    > > qsort compare function in a completely typesafe manner with no
    > > casts, which is much cleaner code:
    > >
    > > int intcmp(const void *va, const void *vb)
    > > {
    > > const int *a = va, *b = vb;
    > > return *a - *b;
    > > }
    > >

    > Friends,
    > Don't we have to cast a void* so that the void points to a valid
    > value (as per 6.3.2.3 of the standard). (Correct me if I am wrong):
    >


    No, this isn't C++.

    The standard states that:
    ``A pointer to void may be converted to or from a pointer to any incomplete
    or object
    type. A pointer to any incomplete or object type may be converted to a
    pointer to void
    and back again; the result shall compare equal to the original pointer.''


    And for simple assignment(which also applies to initialization) that:
    ``One operand is a pointer to an object or incomplete type and the other
    is a pointer to a qualified or unqualified version of void, and the type
    pointed to by the left has all the qualifiers of the type pointed to by
    the right''

    Which makes casting in this case entirely unnecessary.

    example.c:
    #include <stdio.h>
    int main(void)
    {
    unsigned int i;
    unsigned int *p;
    void *p1;

    p = &i;
    p1 = p;
    p = p1;

    if(p == p1)
    puts("They compare equal.");
    else
    puts("Get a new compiler.");

    return 0;
    }


    > int fun(const void *a, const void *b)
    > {
    > unsigned int *p , *q;
    > p =(unsigned int*) a, q =(unsigned int*) b;
    > /*return (*p > *q ) - (*p < *q); */
    > return *p - *q;
    > }
    > int main(void)
    > {
    > int a=2,b=2,c=8,d=6;
    > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > return 0;
    > }
    >
    > OUTPUT:
    >
    > 0 2
    >
    > And for the second one:
    >
    > int fun(const void *a, const void *b)
    > {
    > unsigned int *p , *q;
    > p =(unsigned int*) a, q =(unsigned int*) b;
    > return (*p > *q ) - (*p < *q);
    > /*return *p - *q; */
    > }
    > int main(void)
    > {
    > int a=2,b=2,c=8,d=6;
    > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > return 0;
    > }
    >
    > OUTPUT:
    > 0 1
    >
    > Is there any UB?
    >
    >
    >
    >
    > > That way you will get a diagnostic message from the compiler if
    > > you accidentally attempt to modify the contents of the memory.
     
    j, Oct 4, 2003
    #11
  12. herrcho

    Guest

    "j" <> wrote in message news:<_oCfb.16185$>...
    > <> wrote in message
    > news:...
    > > "Simon Biber" <> wrote in message

    > news:<3f7d8e5d$0$26924$>...
    > > > "herrcho" <> wrote:
    > > > > int intcmp(const void *a, const void *b)
    > > > > {
    > > > > return (*(int*)a - *(int*)b);
    > > > > }
    > > > >
    > > > > in the above , if i put just 'void' instead of 'const void' as a
    > > > > parameter,
    > > > >
    > > > > what's the difference ?
    > > >
    > > > If you're intending to pass this function to qsort or something
    > > > that expects a parameter of type int(*)(const void*,const void*)
    > > > then you must not change from const void to void, this will be
    > > > a constraint violation (wrong type of argument) or else undefined
    > > > behaviour (if you say cast it back to the right type).
    > > >
    > > > > i can't get the meaning of const when used in parameter..
    > > >
    > > > When used as 'const type *a' it means that you are not allowed to
    > > > modify the thing that the pointer is pointing to. Unfortunately
    > > > due to the bad way you wrote the function this protection is lost
    > > > when you cast the argument to (int*). You can in fact write any
    > > > qsort compare function in a completely typesafe manner with no
    > > > casts, which is much cleaner code:
    > > >
    > > > int intcmp(const void *va, const void *vb)
    > > > {
    > > > const int *a = va, *b = vb;
    > > > return *a - *b;
    > > > }
    > > >

    > > Friends,
    > > Don't we have to cast a void* so that the void points to a valid
    > > value (as per 6.3.2.3 of the standard). (Correct me if I am wrong):
    > >

    >
    > No, this isn't C++.


    I don't have C++ standard.I have the slandered ISO-C-1999-04, which
    has got the same words as you mentioned.

    > The standard states that:
    > ``A pointer to void may be converted to or from a pointer to any incomplete
    > or object
    > type. A pointer to any incomplete or object type may be converted to a
    > pointer to void
    > and back again; the result shall compare equal to the original pointer.''
    >
    >
    > And for simple assignment(which also applies to initialization) that:
    > ``One operand is a pointer to an object or incomplete type and the other
    > is a pointer to a qualified or unqualified version of void, and the type
    > pointed to by the left has all the qualifiers of the type pointed to by
    > the right''
    >
    > Which makes casting in this case entirely unnecessary.

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    No, not in the above case with const void* in the parameter and
    non-const with in the function scope.
    >
    > example.c:
    > #include <stdio.h>
    > int main(void)
    > {
    > unsigned int i;
    > unsigned int *p;
    > void *p1;
    >
    > p = &i;
    > p1 = p;
    > p = p1;
    >
    > if(p == p1)
    > puts("They compare equal.");
    > else
    > puts("Get a new compiler.");
    >
    > return 0;
    > }
    >
    >
    > > int fun(const void *a, const void *b)
    > > {
    > > unsigned int *p , *q;
    > > p =(unsigned int*) a, q =(unsigned int*) b;
    > > /*return (*p > *q ) - (*p < *q); */
    > > return *p - *q;
    > > }
    > > int main(void)
    > > {
    > > int a=2,b=2,c=8,d=6;
    > > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > > return 0;
    > > }
    > >
    > > OUTPUT:
    > >
    > > 0 2
    > >
    > > And for the second one:
    > >
    > > int fun(const void *a, const void *b)
    > > {
    > > unsigned int *p , *q;
    > > p =(unsigned int*) a, q =(unsigned int*) b;
    > > return (*p > *q ) - (*p < *q);
    > > /*return *p - *q; */
    > > }
    > > int main(void)
    > > {
    > > int a=2,b=2,c=8,d=6;
    > > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > > return 0;
    > > }
    > >
    > > OUTPUT:
    > > 0 1
    > >
    > > Is there any UB?
    > >
    > >
    > >
    > >
    > > > That way you will get a diagnostic message from the compiler if
    > > > you accidentally attempt to modify the contents of the memory.
     
    , Oct 5, 2003
    #12
  13. herrcho

    j Guest

    <> wrote in message
    news:...
    > "j" <> wrote in message

    news:<_oCfb.16185$>...
    > > <> wrote in message
    > > news:...
    > > > "Simon Biber" <> wrote in message

    > > news:<3f7d8e5d$0$26924$>...
    > > > > "herrcho" <> wrote:
    > > > > > int intcmp(const void *a, const void *b)
    > > > > > {
    > > > > > return (*(int*)a - *(int*)b);
    > > > > > }
    > > > > >
    > > > > > in the above , if i put just 'void' instead of 'const void' as a
    > > > > > parameter,
    > > > > >
    > > > > > what's the difference ?
    > > > >
    > > > > If you're intending to pass this function to qsort or something
    > > > > that expects a parameter of type int(*)(const void*,const void*)
    > > > > then you must not change from const void to void, this will be
    > > > > a constraint violation (wrong type of argument) or else undefined
    > > > > behaviour (if you say cast it back to the right type).
    > > > >
    > > > > > i can't get the meaning of const when used in parameter..
    > > > >
    > > > > When used as 'const type *a' it means that you are not allowed to
    > > > > modify the thing that the pointer is pointing to. Unfortunately
    > > > > due to the bad way you wrote the function this protection is lost
    > > > > when you cast the argument to (int*). You can in fact write any
    > > > > qsort compare function in a completely typesafe manner with no
    > > > > casts, which is much cleaner code:
    > > > >
    > > > > int intcmp(const void *va, const void *vb)
    > > > > {
    > > > > const int *a = va, *b = vb;
    > > > > return *a - *b;
    > > > > }
    > > > >
    > > > Friends,
    > > > Don't we have to cast a void* so that the void points to a valid
    > > > value (as per 6.3.2.3 of the standard). (Correct me if I am wrong):
    > > >

    > >
    > > No, this isn't C++.

    >
    > I don't have C++ standard.I have the slandered ISO-C-1999-04, which
    > has got the same words as you mentioned.
    >
    > > The standard states that:
    > > ``A pointer to void may be converted to or from a pointer to any

    incomplete
    > > or object
    > > type. A pointer to any incomplete or object type may be converted to a
    > > pointer to void
    > > and back again; the result shall compare equal to the original

    pointer.''
    > >
    > >
    > > And for simple assignment(which also applies to initialization) that:
    > > ``One operand is a pointer to an object or incomplete type and the other
    > > is a pointer to a qualified or unqualified version of void, and the type
    > > pointed to by the left has all the qualifiers of the type pointed to by
    > > the right''
    > >
    > > Which makes casting in this case entirely unnecessary.

    > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    > No, not in the above case with const void* in the parameter and
    > non-const with in the function scope.
    > >


    Where is the type in the ``intcmp'' function which is not qualified by
    const?
    I can see two pointer to ints qualified by const being initialized with two
    pointers to void which are also qualified by const.

    > > example.c:
    > > #include <stdio.h>
    > > int main(void)
    > > {
    > > unsigned int i;
    > > unsigned int *p;
    > > void *p1;
    > >
    > > p = &i;
    > > p1 = p;
    > > p = p1;
    > >
    > > if(p == p1)
    > > puts("They compare equal.");
    > > else
    > > puts("Get a new compiler.");
    > >
    > > return 0;
    > > }
    > >
    > >
    > > > int fun(const void *a, const void *b)
    > > > {
    > > > unsigned int *p , *q;
    > > > p =(unsigned int*) a, q =(unsigned int*) b;
    > > > /*return (*p > *q ) - (*p < *q); */
    > > > return *p - *q;
    > > > }
    > > > int main(void)
    > > > {
    > > > int a=2,b=2,c=8,d=6;
    > > > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > > > return 0;
    > > > }
    > > >
    > > > OUTPUT:
    > > >
    > > > 0 2
    > > >
    > > > And for the second one:
    > > >
    > > > int fun(const void *a, const void *b)
    > > > {
    > > > unsigned int *p , *q;
    > > > p =(unsigned int*) a, q =(unsigned int*) b;
    > > > return (*p > *q ) - (*p < *q);
    > > > /*return *p - *q; */
    > > > }
    > > > int main(void)
    > > > {
    > > > int a=2,b=2,c=8,d=6;
    > > > printf("%d %d\n",fun(&a,&b),fun(&c,&d));
    > > > return 0;
    > > > }
    > > >
    > > > OUTPUT:
    > > > 0 1
    > > >
    > > > Is there any UB?
    > > >
    > > >
    > > >
    > > >
    > > > > That way you will get a diagnostic message from the compiler if
    > > > > you accidentally attempt to modify the contents of the memory.
     
    j, Oct 5, 2003
    #13
  14. herrcho

    Kevin Bracey Guest

    In message <>
    CBFalconer <> wrote:

    > pete wrote:
    > > > > return (*a > *b) - (*a < *b);
    > > > return (*a < *b) ? -1 : (*a > *b);

    > >
    > > I see two unconditional comparisons and a subtraction in the first,
    > > but only two comparisons, with one of them being conditional,
    > > in the second.


    Actually, both cases will probably only need to have one actual comparison on
    most architectures, with a multi-way set of conditions following.

    > However the emitted code will often not have any jumps in it (for
    > the first), which avoids flushing any instruction queues. I
    > learned it from someone, and consider it a trick worth knowing.


    Isn't micro-optimisation great?

    > The point is that they are both safe, and have a chance to
    > simultaneously be efficient and clear. However there may be
    > considerable code involved in converting a machine comparison into
    > the 0 or 1 representation, in which case the ?: coding will be
    > superior.


    Also, conditional execution (as found in the ARM) tends to render such jump
    avoidance counter-productive, as there are unlikely to be any branches
    involved in such a simple condition. The subtraction comes out as the
    tedious:

    intcmp
    LDR a1,[a1]
    LDR a2,[a2]
    CMP a1,a2
    MOVLE a1,#0
    MOVGT a1,#1
    MOVGE a2,#0
    MOVLT a2,#1
    SUB a1,a1,a2
    MOV pc,lr

    Whereas the ? : form wins by 1-4 cycles:

    intcmp
    LDR a1,[a1]
    LDR a2,[a2]
    CMP a1,a2
    MVNLT a1,#0
    MOVLT pc,lr
    MOVLE a1,#0
    MOVGT a1,#1
    MOV pc,lr

    --
    Kevin Bracey, Principal Software Engineer
    Tematic Ltd Tel: +44 (0) 1223 503464
    182-190 Newmarket Road Fax: +44 (0) 1223 503458
    Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
     
    Kevin Bracey, Oct 7, 2003
    #14
    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. p|OtrEk

    const type& and type const&

    p|OtrEk, Jul 17, 2005, in forum: C++
    Replies:
    6
    Views:
    415
    Ben Pope
    Jul 17, 2005
  2. Replies:
    11
    Views:
    1,151
  3. Javier
    Replies:
    2
    Views:
    621
    James Kanze
    Sep 4, 2007
  4. 0m
    Replies:
    26
    Views:
    1,171
    Tim Rentsch
    Nov 10, 2008
  5. paulo
    Replies:
    9
    Views:
    741
    James Kanze
    Mar 6, 2009
Loading...

Share This Page