Thread: I thought I understood but....(pointer question)

  1. #1
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751

    I thought I understood but....(pointer question)

    Pardon the seemingly excessive usage of code in advance:

    Twice now I've gotten to a point in C where I feel comfortable only to come back and have the rug taken out from under me - as if I misunderstood the lesson and went along my way doing it wrong all the way.
    I just yesterday finished a exercise in my book C primer plus 4th edition that asked me to sort an array of struct alphabetically. I used the selection sort algorithm as in the following code
    Code:
    void Show(struct CAF arg[]){
         int ndx,ndx2;
         struct CAF *temp;
         struct CAF *ptr_arg[SEAT_NUM];
         
     /*assign ptr_struct the proper addy */
          for(ndx=0;ndx<SEAT_NUM;ndx++)
         ptr_arg[ndx] = &arg[ndx];
    
    /*sort the structures; if struct nxt comes before struct prev then swap them */
        for(ndx=0;ndx<SEAT_NUM;ndx++){
          for(ndx2=ndx+1;ndx2<SEAT_NUM;ndx2++){
          if( (strcmp(ptr_arg[ndx2]->LastName,ptr_arg[ndx]->LastName) ) < 0){//comes before 
            temp = ptr_arg[ndx2];
            ptr_arg[ndx2] = ptr_arg[ndx];
            ptr_arg[ndx] = temp;
            }
        }
    }
         
    /*show the sorted list but only sort the ones that are TAKEN SHOULD APPLY 
    this to the sort logic above as well. only sort the ones that are taken. less
    time and more efficient*/
    for(ndx=0;ndx<SEAT_NUM;ndx++)
          if ( (ptr_arg[ndx]->SeatStatus==TAKEN) )
              printf("seat %d: %s, %s\n", ptr_arg[ndx]->SeatNum,ptr_arg[ndx]->LastName,
              ptr_arg[ndx]->FirstName);
    }
    assuimg a struct of
    Code:
    struct CAF{
           int SeatNum;
           int SeatStatus;
           char LastName[MAX];
           char FirstName[MAX];
           };
           
    struct CAF Seats[SEAT_NUM];
    now originally my code was as follows
    Code:
    /*show the sorted list */
    for(ndx=0;ndx<SEAT_NUM;ndx++)
          if ( (arg[ndx]).SeatStatus )
              printf("seat %d: %d %s %s\n", arg[ndx].SeatNum,arg[ndx].SeatStatus,arg[ndx].FirstName,
              arg[ndx].LastName);
    and I was shown the error of my ways. My question is why? As far as i understood and working under that assumption: a pointer stores the address of a var. dereference that pointer you canget to that addy of the object and change its value via the pointer.
    ptrs enable you to change objects values in different scopes. so why
    when sorted do i need to put addy of the ptr_arg and not the arg itself
    my understanding up to this point where they were one and the same and
    you put const if you didn't want to change the value the ptr pointed to?

    examples which served to reinforce my belief were such things as a simple swap code
    Code:
    #include <stdio.h>
    void interchange(int * , int * );
    int main(void)
    {
        int x = 5, y = 10;
        
    
        printf("Originally x = %d and y = %d.\n", x, y);
        interchange(&x, &y);  /* send addresses to function  */
        printf("Now x = %d and y = %d.\n", x, y);
        getchar();
        return 0;
    }
    
    void interchange(int * x, int * y)
    {
        int temp;/*temp just needs to hold an integer, not a pointer */
    
        temp = *x;       /* temp gets value that u points to */
        *x= *y;
        *y= temp;/*which was x */
    }
    the original values are obviously change by using pointers to get to their addy's.
    To confound me even more
    Code:
    /* names1.c -- passes structures by reference to funcions.*/
    #include <stdio.h>
    #include <string.h>
    
    struct namect {
        char fname[20];
        char lname[20];
        int letters;
    };
    void getinfo(struct namect *);
    void makeinfo(struct namect *);
    void showinfo(const struct namect *);
    int main(void)
    {
        struct namect person;
    
        getinfo(&person);
        makeinfo(&person);
        //showinfo(&person); /*uses *person to change info */
        
    /*this was changed using a pointer to person so it changed the struct */
        puts(person.fname);
        puts(person.lname);
        printf("you have %d lets in your name",person.letters);
       
        getchar();
        return 0;
    }
    
    void getinfo (struct namect * pst)
    {
        printf("Please enter your first name.\n");
        gets(pst->fname);
        printf("Please enter your last name.\n");
        gets(pst->lname);
    }
    
    void makeinfo (struct namect * pst)
    {
        pst->letters = strlen(pst->fname) +
                       strlen(pst->lname);
    }
    
    void showinfo (const struct namect * pst)
    {
        printf("%s %s, your name contains %d letters.\n",
            pst->fname, pst->lname, pst->letters);
    }
    As you can see Show info changed the info at person.firstname and letters and instead of using pst->fname to print that change i used the original value because it is changed right?
    Then last piece of code is this
    Code:
    /* sort_str.c -- reads in strings and sorts them */
    #include <stdio.h>
    #include <string.h>
    #define SIZE 81        /* string length limit, including \0  */
    /* is this really necessary though */
    #define LIM 20         /* maximum number of lines to be read */
    #define HALT ""        /* null string to stop input          */
    void stsrt(char *strings[], int num);/* string-sort function */
    int main(void)
    {
      char input[LIM][SIZE];       /* array to store input       */
      char *ptstr[LIM];            /* array of pointer variables */
      int ct = 0;                  /* input count                */
      int k;                       /* output count               */
    
      printf("Input up to %d lines, and I will sort them.\n",LIM);
      printf("To stop, press the Enter key at a line's start.\n");
      while (ct < LIM && gets(input[ct]) != NULL && input[ct][0] != '\0')
      /* this terminates input as it points to null this is the first letter of the word being 
      entered, as long as its not '\0' then its a word. I see*/
      
                                  
      {
         ptstr[ct] = input[ct];    /* set ptrs to strings. this copies the words to ptstr      */
         ct++;//increment word count
      }
      stsrt(ptstr, ct);            /* string sorter, and the number of words to sort */
      puts("\nHere's the sorted list:\n");
      for (k = 0; k < ct; k++)
    
         puts(ptstr[k]) ;           
      getchar();
      return 0;
    }
    /* string-pointer-sorting function using selection sort algorithm. this sorts
    pointers to char not the actual words themselves?? */
    void stsrt(char *strings[], int num)
    /* this sorts an array of pointers. so its sorting the first letter of each pointer and it
    moves up*/
    {
      char *temp;
      int top, seek;
    
      for (top = 0; top < num-1; top++)/* num - 1 is the element -1 for the null character */
         for (seek = top + 1; seek < num; seek++)
            if (strcmp(strings[top],strings[seek]) > 0)//if top comes before seek
            
            {
                temp = strings[top];
                strings[top] = strings[seek];
                strings[seek] = temp;
            }
    }
    this code read back what you sorted. but if I replace ptsr with input value would remain unchange.
    obvioulsy its only sorting ptsr but why, ptsr is a *input so any changes to ptsr unless it is
    qualified as constant should result in changes to input as well.
    you use ptrs_totype to avoid making auto copies of objects and wasting memory. I understand that
    but how is that input remains unchanged, what am i missing???
    I'm utterly confused by this. Someone please put in a light I can understand cause I can't imagine what piece of info i'm missing to click it into place. Its annoying!!!
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    As far as i understood and working under that assumption: a pointer stores the address of a var. dereference that pointer you canget to that addy of the object and change its value via the pointer.
    1) A pointer stores a value, just like every other variable.
    2) The value a pointer stores is the memory address of a variable of its type.

    Code:
    int foo;
    int *bar;
    In the above, foo is an int, and bar is a pointer which stores the address of an int. It's as simple as that.
    3) To get the address of a variable, you use the address-of operator, which is the ampersand: &

    Code:
    int foo;
    int *bar;
    
    foo = 10;
    bar = &foo;
    Here we get the address of foo and store it in bar. Remember that pointers store addresses of their type. Bar stores the address of an integer, so we give it that.
    4) You can dereference a pointer, to access the memory whose address it stores. You do this with the dereference operator: *

    Code:
    int foo;
    int *bar;
    int baz;
    
    foo = 10;
    bar = &foo;
    
    baz = *bar;
    Here we access the memory which bar points to by dereferencing it. This gives us the value stored at the memory location itself. We can make assignments to that memory address, like you would a normal variable assignment, or we can access it to see what value is there. (Just like any other variable.

    My question is why? As far as i understood and working under that assumption: a pointer stores the address of a var. dereference that pointer you canget to that addy of the object and change its value via the pointer.
    ptrs enable you to change objects values in different scopes. so why
    when sorted do i need to put addy of the ptr_arg and not the arg itself
    my understanding up to this point where they were one and the same and
    you put const if you didn't want to change the value the ptr pointed to?
    In your code, you don't do anything to the origional array itself. You simply create another array, of pointers to that type, and for the scope of that function, you sort them. Once the function has ended, it's gone, because you don't actually modify the origional array. Let's examine:
    Code:
    void Show(struct CAF arg[] /* 1 */ ){
         int ndx,ndx2;
         struct CAF *temp;
         struct CAF *ptr_arg[SEAT_NUM]; /* 2 */
         
     /*assign ptr_struct the proper addy */
          for(ndx=0;ndx<SEAT_NUM;ndx++) 
         ptr_arg[ndx] = &arg[ndx]; /* 3 */
    1) Here, you pass the function an array of type struct CAF.
    2) You then create an array of pointers to that type.
    3) You next assign the array the address of every structure in the array.

    Code:
    /*sort the structures; if struct nxt comes before struct prev then swap them */
        for(ndx=0;ndx<SEAT_NUM;ndx++){
          for(ndx2=ndx+1;ndx2<SEAT_NUM;ndx2++){
          if( (strcmp(ptr_arg[ndx2]->LastName,ptr_arg[ndx]->LastName) ) < 0){//comes before 
            temp = ptr_arg[ndx2]; /* 4 */
            ptr_arg[ndx2] = ptr_arg[ndx];
            ptr_arg[ndx] = temp;
            }
        }
        /* 5 */
    }
    4) You now swap the value of the pointers inside the array of pointers.
    5) The function ends, and the origional array is unmodified.

    Now look at that again, and read what I've outlined. You created a second array, of pointers, and moved elements in that array around. You have sorted that array, not the origional array. The origional array is unchanged. Yes, you can change the value of what pointers point at, but no, you don't do that. You change the value of each pointer, not the value of what each pointer points at.

    You don't do anything but sort an array of pointers. You never actually do anything with the origional array.

    examples which served to reinforce my belief were such things as a simple swap code
    Yes, but in the swap code, you're passing the addresses of the variables you want to swap. This is different than what you do above. Let's modify the swap code to do what you have done, and then you'll see where you went off track:
    Code:
    #include <stdio.h>
    void interchange( int values[] );
    
    int main(void)
    {
        int foo[2] = { 5, 10 };
    
        printf("Originally x = %d and y = %d.\n", foo[0], foo[1] );
        interchange( foo );  /* send array to function  */
        printf("Now x = %d and y = %d.\n", foo[0], foo[1] );
        getchar();
        return 0;
    }
    
    void interchange( int values[] )
    {
        int *foo[2]; /* so we can store the addresses of the array's individual cells */
        int *temp; /* so we can swap them */
    
        foo[0] = &values[0]; /* store the addresses */
        foo[1] = &values[1];
    
        temp = foo[0];    /* temp gets value that u points to */
        foo[0] = foo[1];
        foo[1] = temp;    /*which was x */
    }
    See what you've done? You create a second array, without modifying the origional one, and simply swap the values of what each spot in that new array contain.

    What you should have been doing, is simply swapping the value of each array's data around, like is done in this version of the interchange function:
    Code:
    void interchange( int values[] )
    {
        int temp; /* so we can swap them */
    
        temp = values[0];    /* temp gets value that u points to */
        values[0] = values[1];
        values[1] = temp;    /*which was x */[/color]
    }
    Like so.

    Next segment:
    Code:
    void showinfo (const struct namect * pst)
    {
        printf("%s %s, your name contains %d letters.\n",
            pst->fname, pst->lname, pst->letters);
    }
    As you can see Show info changed the info at person.firstname and letters and instead of using pst->fname to print that change i used the original value because it is changed right?
    No. showinfo doesn't change anything. It simply dereferences what is in the structure. You make no assignments in this function, and without making an assignment, you cannot change anything. You are only "looking at", or dereferencing that structure. You make no changes to it. Any changes you've made happened outside of this function.

    In the last code, you have the same problem as in the first. You're not understanding how arrays work when passed to functions, and how arrays of pointers work.

    An array of pointers, when sorted, is just like an array of "regular" variables when sorted. You are switching around the values of that array. If you sort an array of pointers some how, you are simply rearranging that array, not what those pointers point to. THAT array. The array you're modifying is the only one being changed.

    If you modify an array of pointers, that array is changed. If you modify an array of non-pointers, that array is being changed.

    You seem to be hung up on something very simple: If you create another variable, and modify that new variable, it and it alone is being changed. You're effectively doing this:
    Code:
    int x = 10;
    int y = x;
    
    y = y + 10;
    printf("%d", x );
    "Why isn't x being changed?"
    That's basicly what you're doing when you're making the array of pointers. You make a new variable, change it, and wonder why the first variable doesn't change.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. Easy pointer question
    By Edo in forum C++ Programming
    Replies: 3
    Last Post: 01-19-2009, 10:54 AM
  3. char pointer to pointer question
    By Salt Shaker in forum C Programming
    Replies: 3
    Last Post: 01-10-2009, 11:59 AM
  4. A pointer question.
    By joenching in forum C++ Programming
    Replies: 7
    Last Post: 03-20-2008, 04:10 PM
  5. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM