sort of list of pointers

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • MisterE

    sort of list of pointers

    // Is any of this not portable correct etc?
    #include <stdlib.h>

    typedef struct b
    {
    int f;
    } B;

    //Should pointers to pointers be avoided or nothing wrong with this:
    int compare( const void *arg1, const void *arg2 )
    {
    B **b1;
    B **b2;
    b1 = (B **)arg1;
    b2 = (B **)arg2;
    //And are there any reasons to use 1 of these lines over the other:
    return ((**b1).f - (**b2).f);
    //return (*b1)->f - (*b2)->f;
    }

    int main (int argc, char *argv[])
    {
    B **list;
    int j = 100;
    list = malloc(sizeof(B *)*j);
    if (list == NULL) return -1;
    while(j)
    {
    j--;
    list[j] = malloc(sizeof(B ));
    if (list[j] == NULL) return -2;
    list[j]->f = j;
    }
    qsort(list,100, sizeof(B *),compare);
    return 0;
    }



  • pete

    #2
    Re: sort of list of pointers

    MisterE wrote:
    // Is any of this not portable correct etc?
    It's OK as written.
    The return values of -1 and -2 from main,
    don't have portable meanings.
    #include <stdlib.h>
    >
    typedef struct b
    {
    int f;
    } B;
    >
    //Should pointers to pointers be avoided or nothing wrong with this:
    int compare( const void *arg1, const void *arg2 )
    {
    B **b1;
    B **b2;
    b1 = (B **)arg1;
    b2 = (B **)arg2;
    //And are there any reasons to use 1 of these lines over the other:
    Either of those two lines are OK for the limited range of int
    in the program
    return ((**b1).f - (**b2).f);
    //return (*b1)->f - (*b2)->f;
    }
    >
    int main (int argc, char *argv[])
    {
    B **list;
    int j = 100;
    list = malloc(sizeof(B *)*j);
    if (list == NULL) return -1;
    while(j)
    {
    j--;
    list[j] = malloc(sizeof(B ));
    if (list[j] == NULL) return -2;
    list[j]->f = j;
    }
    qsort(list,100, sizeof(B *),compare);
    return 0;
    }
    /* BEGIN new.c */

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

    #define J_INIT 100

    typedef struct b {
    int f;
    } B;

    int compare( const void *arg1, const void *arg2 )
    {
    B **b1 = (B **)arg1;
    B **b2 = (B **)arg2;

    return (*b2) -f (*b1) -f ? -1
    : (*b2) -f != (*b1) -f;
    }

    int main(void)
    {
    B **list;
    int j = J_INIT;

    list = malloc(j * sizeof(*list));
    if (list == NULL) {
    puts("list == NULL");
    return EXIT_FAILURE;
    }
    while (j-- != 0) {
    list[j] = malloc(sizeof *list[j]);
    if (list[j] == NULL) {
    puts("list[j] == NULL");
    return EXIT_FAILURE;
    }
    list[j] -f = -j;
    }
    for (j = 0; j != J_INIT; ++j) {
    printf("%d ", list[j] -f);
    }
    puts("\n");
    qsort(list, J_INIT, sizeof *list, compare);
    for (j = 0; j != J_INIT; ++j) {
    printf("%d ", list[j] -f);
    }
    putchar('\n');
    for (j = 0; j != J_INIT; ++j) {
    free(list[j]);
    }
    free(list);
    return 0;
    }

    /* END new.c */

    --
    pete

    Comment

    • Richard Heathfield

      #3
      Re: sort of list of pointers

      MisterE said:
      // Is any of this not portable correct etc?
      #include <stdlib.h>
      >
      typedef struct b
      {
      int f;
      } B;
      >
      //Should pointers to pointers be avoided or nothing wrong with this:
      int compare( const void *arg1, const void *arg2 )
      {
      B **b1;
      B **b2;
      b1 = (B **)arg1;
      b2 = (B **)arg2;
      //And are there any reasons to use 1 of these lines over the other:
      return ((**b1).f - (**b2).f);
      //return (*b1)->f - (*b2)->f;
      As far as (**b1).f vs (*b1)->f goes, it's really a matter of taste.

      I would do it this way:

      int compare(const void *arg1, const void *arg2)
      {
      B *const *pb1 = arg1;
      B *const *pb2 = arg2;
      B *b1 = *pb1;
      B *b2 = *pb2;
      return (b1->f b2->f) - (b1->f < b2->f);
      }

      Wordy, but clear, and eliminates the possibility of arithmetic overflow.
      >
      int main (int argc, char *argv[])
      {
      B **list;
      int j = 100;
      list = malloc(sizeof(B *)*j);
      I'd write:

      list = malloc(j * sizeof *list);
      list[j] = malloc(sizeof(B ));
      And here I'd write:

      list[j] = malloc(sizeof *list[j]);

      Cf pete's reply re return values.

      --
      Richard Heathfield <http://www.cpax.org.uk >
      Email: -http://www. +rjh@
      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
      "Usenet is a strange place" - dmr 29 July 1999

      Comment

      • Barry Schwarz

        #4
        Re: sort of list of pointers

        On Sat, 27 Sep 2008 08:48:44 +1000, MisterE <mistere@no.ema il.ok>
        wrote:
        >// Is any of this not portable correct etc?
        // comments are not portable unless you are restricting yourself to
        C99 systems.
        >#include <stdlib.h>
        >
        >typedef struct b
        >{
        int f;
        >} B;
        >
        >//Should pointers to pointers be avoided or nothing wrong with this:
        When sorting pointers it is almost impossible to avoid them.

        Why should any feature of the language be avoided?
        >int compare( const void *arg1, const void *arg2 )
        >{
        B **b1;
        B **b2;
        b1 = (B **)arg1;
        b2 = (B **)arg2;
        //And are there any reasons to use 1 of these lines over the other:
        return ((**b1).f - (**b2).f);
        //return (*b1)->f - (*b2)->f;
        Either can overflow. You might want to consider using comparisons
        (possibly with the conditional operator).
        >}
        >
        >int main (int argc, char *argv[])
        >{
        B **list;
        int j = 100;
        list = malloc(sizeof(B *)*j);
        if (list == NULL) return -1;
        EXIT_FAILURE, EXIT_SUCCESS, and 0 are the only portable return values
        from main.
        while(j)
        {
        j--;
        list[j] = malloc(sizeof(B ));
        if (list[j] == NULL) return -2;
        list[j]->f = j;
        }
        qsort(list,100, sizeof(B *),compare);
        return 0;
        >}
        >
        >
        --
        Remove del for email

        Comment

        • Ian Collins

          #5
          Re: sort of list of pointers

          pete wrote:
          >
          /* BEGIN new.c */
          >
          #include <stdlib.h>
          #include <stdio.h>
          >
          #define J_INIT 100
          >
          typedef struct b {
          int f;
          } B;
          >
          int compare( const void *arg1, const void *arg2 )
          {
          B **b1 = (B **)arg1;
          B **b2 = (B **)arg2;
          >
          return (*b2) -f (*b1) -f ? -1
          : (*b2) -f != (*b1) -f;
          I do hate comparisons where one has to ponder what's going on. Why not
          something like

          int compare( const void *arg1, const void *arg2 )
          {
          /* Do the messy stuff in one place.
          */
          int lhs = (*(const B**)(arg1))->f;
          int rhs = (*(const B**)(arg2))->f;

          return lhs == rhs ? 0 : lhs rhs ? 1 : -1;
          }

          or even;

          if (i j) return 1;
          if (i < j) return -1;
          return (0);

          --
          Ian Collins.

          Comment

          Working...