Problems with Pointers

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • stevenruiz@gmail.com

    Problems with Pointers

    Hello All

    My question mainly is how to use/reference Double Pointers? I am
    currently trying to understand what the meaning of a 'vector of
    pointers' means also? What I am trying to do is take a char array and
    break it up into words omitting the spaces. What needs to be noted is
    that I am trying to accomplish this only using char ** and char *.
    Therefore, I am creating it from scratch. Below is code that I have
    written so far:

    int main()
    {
    char input[125] = " Hello World\0"
    char **doublePointer ;
    char *receiveArray;

    doublePointer = malloc(125 * sizeof(char *));
    receiveArray = input;

    int i;
    for(i = 0; receiveArray [ i ] != '\0'; i++)
    {
    //Here I am confused
    //I'm not sure how to traverse the array and store data into
    // the double pointer/vector
    //Do I need to do this
    // doublePointer [ i ] = malloc ( sizeof( char * ));
    }


    free(doublePoin ter);

    return 0;
    }

    Any hints and suggestions about the algorithm/design would be
    welcome. Thanks.
  • Ben Bacarisse

    #2
    Re: Problems with Pointers

    stevenruiz@gmai l.com writes:
    My question mainly is how to use/reference Double Pointers? I am
    currently trying to understand what the meaning of a 'vector of
    pointers' means also? What I am trying to do is take a char array and
    break it up into words omitting the spaces. What needs to be noted is
    that I am trying to accomplish this only using char ** and char *.
    Therefore, I am creating it from scratch. Below is code that I have
    written so far:
    Why start with main? What function would really, really help to solve
    this? Image it exists and take it from there. Then all you need do
    is write that now slightly simpler function.

    Personally, I want a function declared like this:

    char *next_word(cons t char **string);

    /* Returns a pointer to a copy (in malloc'd storage) of the
    * next word found in *string. *string is updated to point to
    * first character found that is not part of the work returned.
    * If no word is found, NULL is returned.
    */

    With this function in the bag, I'd expect to see a relatively simple
    loop, putting the returned pointers into elements of a char * array.
    For bonus marks, I'd hope to see a loop that reallocs this array if
    more words than expected are found.

    Now you just need to write next_word. What function would really,
    really help to write next_word? Image it exists and take it from
    there...
    int main()
    {
    char input[125] = " Hello World\0"
    char **doublePointer ;
    char *receiveArray;
    >
    doublePointer = malloc(125 * sizeof(char *));
    If you are going to use 125, just declare

    char *doublePointer[125];

    BTW, that is a terrible name! Name you variables with what that mean
    (usually what they contain) not what type they have.
    receiveArray = input;
    >
    int i;
    for(i = 0; receiveArray [ i ] != '\0'; i++)
    {
    //Here I am confused
    //I'm not sure how to traverse the array and store data into
    // the double pointer/vector
    //Do I need to do this
    // doublePointer [ i ] = malloc ( sizeof( char * ));
    I would not start in the middle of a loop in main, sorry.
    }
    >
    >
    free(doublePoin ter);
    >
    return 0;
    }
    >
    Any hints and suggestions about the algorithm/design would be
    welcome. Thanks.
    --
    Ben.

    Comment

    • Micheal Smith

      #3
      Re: Problems with Pointers

      On Sun, 31 Aug 2008 20:00:44 -0700, stevenruiz wrote:
      Hello All
      >
      My question mainly is how to use/reference Double Pointers? I am
      currently trying to understand what the meaning of a 'vector of
      pointers' means also? What I am trying to do is take a char array and
      break it up into words omitting the spaces. What needs to be noted is
      that I am trying to accomplish this only using char ** and char *.
      Therefore, I am creating it from scratch. Below is code that I have
      written so far:
      >
      int main()
      {
      char input[125] = " Hello World\0"
      char **doublePointer ;
      char *receiveArray;
      >
      doublePointer = malloc(125 * sizeof(char *)); receiveArray = input;
      >
      int i;
      for(i = 0; receiveArray [ i ] != '\0'; i++) {
      //Here I am confused
      //I'm not sure how to traverse the array and store data into //
      the double pointer/vector
      //Do I need to do this
      // doublePointer [ i ] = malloc ( sizeof( char * ));
      }
      >
      >
      free(doublePoin ter);
      >
      return 0;
      }
      >
      Any hints and suggestions about the algorithm/design would be welcome.
      Thanks.
      To answer the OP question. A vector of pointers is an array of pointers
      that implements a multidimensiona l array. Your assumption for accessing
      the array of pointer seems correct as far as I can tell.

      Comment

      • Barry Schwarz

        #4
        Re: Problems with Pointers

        On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), stevenruiz@gmai l.com wrote:
        >Hello All
        >
        My question mainly is how to use/reference Double Pointers? I am
        >currently trying to understand what the meaning of a 'vector of
        >pointers' means also? What I am trying to do is take a char array and
        The phrase has no defined meaning in the standard. Since the word
        vector also has no special meaning in C, I would take the phrase to be
        synonymous with "array of pointers".
        >break it up into words omitting the spaces. What needs to be noted is
        Define break it up.

        Do you want to replace the word separators (usually a space)
        with '\0' so that the array now contains multiple strings, each
        corresponding to a word? If so, do you want to build an array of
        pointers that points to each word?

        Or do you want to copy the portions of the string that
        constitute words to new arrays of char? If so, do you want the
        resulting arrays to contain valid strings or just the characters in
        the words? Do you want to define the target arrays or dynamically
        allocate them?
        >that I am trying to accomplish this only using char ** and char *.
        This is probably adequate for this task but why would you arbitrarily
        limit yourself to a subset of the language? Usually arbitrary
        restrictions like this are a sure sign of homework.
        >Therefore, I am creating it from scratch. Below is code that I have
        >written so far:
        Writing code before the intent is defined is perilous.
        >
        int main()
        {
        char input[125] = " Hello World\0"
        char **doublePointer ;
        char *receiveArray;
        >
        doublePointer = malloc(125 * sizeof(char *));
        Do you really think you will need a char* for char in input?
        receiveArray = input;
        >
        int i;
        for(i = 0; receiveArray [ i ] != '\0'; i++)
        {
        //Here I am confused
        //I'm not sure how to traverse the array and store data into
        // the double pointer/vector
        Until you decide what data to store in the space pointed to by
        doublePointer, we will be unsure also.
        //Do I need to do this
        // doublePointer [ i ] = malloc ( sizeof( char * ));
        This is definitely wrong. doublePointer is a char**. Therefore
        doublePointer[i] is a char*. If you want doublePointer[i] to point to
        dynamically allocated memory, the argument passed to malloc should
        always be the (maximum) number of characters you intend to store in
        that memory. On most system, your code would limit you to 4 or 8.
        This is the reason that many here recommend the following syntax for
        allocating a dynamic array to a pointer named x:
        x = malloc(number_o f_elements_desi red * sizeof *x);
        }
        >
        >
        free(doublePoin ter);
        If doublePointer and all the doublePointer[i] point to allocated
        memory, the doublePointer[i] need to be freed before you free
        doublePointer.
        >
        return 0;
        >}
        --
        Remove del for email

        Comment

        • stevenruiz@gmail.com

          #5
          Re: Problems with Pointers

          On Aug 31, 10:57 pm, Barry Schwarz <schwa...@dqel. comwrote:
          On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), stevenr...@gmai l.com wrote:
          Hello All
          >
          My question mainly is how to use/reference Double Pointers? I am
          currently trying to understand what the meaning of a 'vector of
          pointers' means also? What I am trying to do is take a char array and
          >
          The phrase has no defined meaning in the standard. Since the word
          vector also has no special meaning in C, I would take the phrase to be
          synonymous with "array of pointers".
          >
          break it up into words omitting the spaces. What needs to be noted is
          >
          Define break it up.
          >
          Do you want to replace the word separators (usually a space)
          with '\0' so that the array now contains multiple strings, each
          corresponding to a word? If so, do you want to build an array of
          pointers that points to each word?
          >
          Or do you want to copy the portions of the string that
          constitute words to new arrays of char? If so, do you want the
          resulting arrays to contain valid strings or just the characters in
          the words? Do you want to define the target arrays or dynamically
          allocate them?
          >
          that I am trying to accomplish this only using char ** and char *.
          >
          This is probably adequate for this task but why would you arbitrarily
          limit yourself to a subset of the language? Usually arbitrary
          restrictions like this are a sure sign of homework.
          >
          Therefore, I am creating it from scratch. Below is code that I have
          written so far:
          >
          Writing code before the intent is defined is perilous.
          >
          >
          >
          int main()
          {
          char input[125] = " Hello World\0"
          char **doublePointer ;
          char *receiveArray;
          >
          doublePointer = malloc(125 * sizeof(char *));
          >
          Do you really think you will need a char* for char in input?
          >
          receiveArray = input;
          >
          int i;
          for(i = 0; receiveArray [ i ] != '\0'; i++)
          {
          //Here I am confused
          //I'm not sure how to traverse the array and store data into
          // the double pointer/vector
          >
          Until you decide what data to store in the space pointed to by
          doublePointer, we will be unsure also.
          >
          //Do I need to do this
          // doublePointer [ i ] = malloc ( sizeof( char * ));
          >
          This is definitely wrong. doublePointer is a char**. Therefore
          doublePointer[i] is a char*. If you want doublePointer[i] to point to
          dynamically allocated memory, the argument passed to malloc should
          always be the (maximum) number of characters you intend to store in
          that memory. On most system, your code would limit you to 4 or 8.
          This is the reason that many here recommend the following syntax for
          allocating a dynamic array to a pointer named x:
          x = malloc(number_o f_elements_desi red * sizeof *x);
          >
          }
          >
          free(doublePoin ter);
          >
          If doublePointer and all the doublePointer[i] point to allocated
          memory, the doublePointer[i] need to be freed before you free
          doublePointer.
          >
          >
          >
          return 0;
          }
          >
          --
          Remove del for email
          Pretty much what I'm trying to do is create a tokenizer or a (strtok)
          and yes I would like to build an array of
          pointers that points to each word. This is for I return or print out
          to see the words in each position of the array of pointers. I
          understand if I were to have a char[] which had, for example, "hello
          world\0". The way I have been approaching this is first by
          establishing a pointer to that array's first position at the letter
          'h' using char *inputData = <the char array>. At this point, I have
          the beginning of the char array. Next, I was thinking I would loop
          through inputData while it is not equal to a space, I'm thinking that
          I would point that doublePointer to that specific address of inputData
          [ i ]? Please advise.

          Comment

          • zaimoni@zaimoni.com

            #6
            Re: Problems with Pointers

            On Sep 1, 12:46 am, stevenr...@gmai l.com wrote:
            Pretty much what I'm trying to do is create a tokenizer or a (strtok)
            and yes I would like to build an array of
            pointers that points to each word.
            This is for I return or print out
            to see the words in each position of the array of pointers. I
            understand if I were to have a char[] which had, for example, "hello
            world\0".
            Ok.
            The way I have been approaching this is first by
            establishing a pointer to that array's first position at the letter
            'h' using char *inputData = <the char array>. At this point, I have
            the beginning of the char array. Next, I was thinking I would loop
            through inputData while it is not equal to a space, I'm thinking that
            I would point that doublePointer to that specific address of inputData
            [ i ]? Please advise.
            This is pretty much what strtok does (overwriting the original
            character buffer so each token is null-terminated). The main reasons
            not to use strtok for this would be that you don't want to overwrite
            the incoming text buffer, or that you're reimplementing strtok.

            Comment

            • Richard Heathfield

              #7
              Re: Problems with Pointers

              stevenruiz@gmai l.com said:

              <snip>
              Pretty much what I'm trying to do is create a tokenizer or a (strtok)
              and yes I would like to build an array of
              pointers that points to each word.
              Okay. ("To me, the term "double pointer" means the same as "pointer to
              double", just as "char pointer" means "pointer to char", so your use of it
              to mean "pointer to pointer", whilst far from unusual, does seem rather
              strange to me. Just a thought.)
              Please advise.
              Divide and conquer.

              Let's start by counting the number of words in the input string - and we
              will define 'word' as 'a sequence, as long as possible, of one or more
              contiguous characters containing no whitespace characters'. Whilst we
              *could* count as we go along, it's easier if we know in advance how many
              pointers we will need. So:

              #include <stddef.h>
              #include <ctype.h>

              #define NOT_IN_WORD 0
              #define IN_WORD 1

              size_t wc(const char *s)
              {
              size_t count = 0;
              int state = NOT_IN_WORD;
              int space = 0;
              while(*s != '\0')
              {
              space = isspace((unsign ed char)*s);
              if(state == NOT_IN_WORD && !space)
              {
              ++count;
              state = IN_WORD;
              }
              else if(state == IN_WORD && space)
              {
              state = NOT_IN_WORD;
              }
              ++s;
              }
              return count;
              }

              Now let's test that. I added a simple driver, which looks like this:

              #include <stdio.h>

              int main(int argc, char **argv)
              {
              while(argc 0)
              {
              size_t count = wc(argv[--argc]);
              printf("%d\n", count);
              }
              return 0;
              }

              Well, perhaps not the greatest test program in the world, but it allowed me
              to drive the code and convince myself that I'd got it right. Okay, now we
              have a way - wc() - to count the number of words in a string. Fine - now
              we'd like to point at them. Remember, divide and conquer - so we'd like a
              function that can build a sequence of these pointers, rather than have all
              the intestines of this idea clogging up main.

              Because we want to *tokenise* the string, in this simple solution we will
              allow our function to modify the string itself. Note that this isn't
              always what you want - it's "lazy" tokenisation, where we simply point
              into the string at various points. That's fine as long as the string
              persists (and as long as we don't mind hacking at it!).

              Here, then, is a function to do that. Observe its similarities and
              differences with regard to wc() - which it itself calls, by the way:

              #include <stdlib.h>
              #include <assert.h>
              char **wl_build(char *s)
              {
              int space = 0;
              int state = 0;
              size_t thisword = 0;
              size_t wordcount = wc(s);
              char **wl = malloc((wordcou nt + 1) * sizeof *wl);
              if(wl != NULL)
              {
              while(*s != '\0')
              {
              space = isspace((unsign ed char)*s);
              if(state == NOT_IN_WORD && !space)
              {
              wl[thisword++] = s;
              state = IN_WORD;
              }
              else if(state == IN_WORD && space)
              {
              *s = '\0'; /* terminate the token */
              state = NOT_IN_WORD;
              }
              ++s;
              }
              wl[thisword] = NULL; /* list is NULL-terminated */
              }
              assert(thisword == wordcount);
              return wl;
              }

              The alternative to doing this whole state machine thing twice is to count
              and reallocate as we go. Possible, and microscopically faster, but perhaps
              more effort than we'd like to go to, and the code would be messier, harder
              to follow, and harder to maintain.

              Once we have a way of creating such a list, we ought to have a way to
              destroy it:
              void wl_destroy(char ***wl)
              {
              if(wl != NULL)
              {
              free(*wl);
              *wl = NULL;
              }
              }

              And of course we will want a demonstration of how to use it. One easy way
              to do that is to write a print function for it:

              #include <stdio.h>

              void wl_print(char **wl)
              {
              while(*wl != NULL)
              {
              printf("%s\n", *wl++);
              }
              }

              Putting it all together, we throw away our old main(), and write a new one:

              int main(int argc, char **argv)
              {
              while(argc 0)
              {
              char **wl = wl_build(argv[--argc]);
              wl_print(wl);
              wl_destroy(&wl) ;
              }
              return 0;
              }

              Now, that's all very well if we're content to do lazy evaluation. But what
              if we're not? Let's say we need for these tokens to persist beyond the
              lifetime of the string. Oh, and hey, let's say the string is sacrosanct,
              too - we can look, but we'd better not touch.

              Very few modifications are required, as it happens, to what we already
              have, but all the mods are important. Perhaps most significant is the
              addition of a token-duplicating function, since it is this that allows us
              to create token copies that will persist after their originals have either
              ceased to exist or at least changed in some way.

              The creation of token copies allows us to leave the original string
              unmodified, but it slightly complicates the destruction of the word list.

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

              #define NOT_IN_WORD 0
              #define IN_WORD 1

              size_t wc(const char *s)
              {
              size_t count = 0;
              int state = NOT_IN_WORD;
              int space = 0;
              while(*s != '\0')
              {
              space = isspace((unsign ed char)*s);
              if(state == NOT_IN_WORD && !space)
              {
              ++count;
              state = IN_WORD;
              }
              else if(state == IN_WORD && space)
              {
              state = NOT_IN_WORD;
              }
              ++s;
              }
              return count;
              }

              char *token_duplicat e(const char *p, size_t len)
              {
              char *new = malloc(len + 1);
              if(new != NULL)
              {
              memcpy(new, p, len);
              new[len] = '\0';
              }
              return new;
              }

              #include <assert.h>
              char **wl_build(cons t char *s)
              {
              int space = 0;
              int state = 0;
              size_t thisword = 0;
              size_t wordcount = wc(s);
              const char *tokenstart = NULL;
              size_t tokenlen = 0;
              char **wl = malloc((wordcou nt + 1) * sizeof *wl);
              if(wl != NULL)
              {
              while(*s != '\0')
              {
              space = isspace((unsign ed char)*s);
              if(state == NOT_IN_WORD && !space)
              {
              tokenstart = s;
              tokenlen = 0;
              state = IN_WORD;
              }
              else if(state == IN_WORD)
              {
              ++tokenlen;
              if(space)
              {
              wl[thisword++] = token_duplicate (tokenstart, tokenlen);
              state = NOT_IN_WORD;
              }
              else
              {
              }
              }
              ++s;
              }
              /* the last token may be null-terminated rather than space-terminated
              */
              if(state == IN_WORD)
              {
              wl[thisword++] = token_duplicate (tokenstart, ++tokenlen);
              }
              wl[thisword] = NULL; /* list is NULL-terminated */
              }
              assert(thisword == wordcount);
              return wl;
              }

              void wl_destroy(char ***wl)
              {
              if(wl != NULL)
              {
              if(*wl != NULL)
              {
              char **w = *wl;
              while(*w != NULL)
              {
              free(*w++);
              }
              }
              free(*wl);
              *wl = NULL;
              }
              }

              void wl_print(char **wl)
              {
              while(*wl != NULL)
              {
              printf("%s\n", *wl++);
              }
              }

              int main(int argc, char **argv)
              {
              while(argc 0)
              {
              char **wl = wl_build(argv[--argc]);
              wl_print(wl);
              printf("Integri ty of arg: %s\n", argv[argc]);
              wl_destroy(&wl) ;
              }
              return 0;
              }

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

              • zaimoni@zaimoni.com

                #8
                Re: Problems with Pointers

                On Aug 31, 10:00 pm, stevenr...@gmai l.com wrote:
                Hello All
                >
                My question mainly is how to use/reference Double Pointers? I am
                currently trying to understand what the meaning of a 'vector of
                pointers' means also? What I am trying to do is take a char array and
                break it up into words omitting the spaces. What needs to be noted is
                that I am trying to accomplish this only using char ** and char *.
                As a learning exercise: assume we don't #include <string.h?
                Therefore, I am creating it from scratch. Below is code that I have
                written so far:
                >
                int main()
                {
                char input[125] = " Hello World\0"
                \0 is mostly redundant here. The string literal will implicitly have
                a \0 character appended to its representation as an array of
                characters.
                char **doublePointer ;
                array_of_c_stri ngs would be a more descriptive name.
                char *receiveArray;
                >
                doublePointer = malloc(125 * sizeof(char *));
                receiveArray = input;
                There's an easy rewrite to prepare this for isolating into a function,
                but as a concept mockup this works. The rewrite also makes the code
                C90-friendly. (right now it's using the C99 feature of intermixing
                declarations and code).

                In this case, it's a matter of coding style whether to use calloc or
                malloc for doublePointer. Due to how things are defined in C, calloc
                will automatically set all of the pointers in the dynamically
                allocated array to NULL.
                int i;
                for(i = 0; receiveArray [ i ] != '\0'; i++)
                {
                //Here I am confused
                //I'm not sure how to traverse the array and store data into
                // the double pointer/vector
                The loop is using i to traverse the array fine. It's what to do that
                matters.
                //Do I need to do this
                // doublePointer [ i ] = malloc ( sizeof( char * ));
                i is already being used to traverse receiveArray, so it should not be
                used to index into doublePointer. For sake of discussion, assume we
                declared another variable

                int j = 0;

                before entering the loop.

                Also, the proposed malloc is mismatched. Once allocated, the "slots"
                in the array of char* pointed to by doublePointer will be perfectly
                fine to use directly to point to C strings. The malloc expression
                would be read as intending to allocate a char** (array of char*), but
                doublePointer[j] is of type char* .

                Having ruled out strtok as an option, you would be wanting to allocate
                an array of char for each token, of length one longer than the
                observed token length. As 1==sizeof(char) for standard-compliant
                compilers, you could get away with something like the following:

                doublePointer[j] = malloc(token_le ngth+1); /* alternately,
                malloc((token_l ength+1)*sizeof (char)) to look like the other malloc */
                doublePointer[j][token_length+1] = '\0'; /* plain 0 also works in
                place of '\0' */
                strncpy(doubleP ointer[j],receiveArray+i ,token_length); /* requires
                #include <string.h>, could use a for-loop to hand-roll copying
                token_length characters like this */
                ++j; /* adjust strict upper bound upwards. j++; also works. */

                where token_length is some expression you calculated using the other
                variables you need to even track being in a strtok-compatible word, as
                well as i.

                Comment

                • Richard Heathfield

                  #9
                  Re: Problems with Pointers

                  zaimoni@zaimoni .com said:

                  <snip>
                  In this case, it's a matter of coding style whether to use calloc or
                  malloc for doublePointer.
                  No, malloc is the better choice.
                  Due to how things are defined in C, calloc
                  will automatically set all of the pointers in the dynamically
                  allocated array to NULL.
                  Only on platforms where the representation of NULL is all-bits-zero, and
                  real platforms exist on which it is not. (ISTR that the FAQ mentions them
                  - feel free to go look it up if you wish.)

                  <snip>

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

                  • zaimoni@zaimoni.com

                    #10
                    Re: Problems with Pointers

                    On Sep 1, 2:55 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
                    zaim...@zaimoni .com said:
                    >
                    <snip>
                    >
                    In this case, it's a matter of coding style whether to use calloc or
                    malloc for doublePointer.
                    >
                    No, malloc is the better choice.
                    As a correct implementation can be explicitly verified to never
                    inspect the values in the malloc'd array in the first place, malloc is
                    the objectively better choice; the implied memset call has no
                    observable effect.

                    (Regardless of whatever style guidelines that are in force at a
                    specific locale, and whether portability to platforms from the age of
                    the computing dinosaurs where the binary representation of NULL is not
                    all-zero-bits is a concern. Obviously, the following paragraph should
                    have been qualified with "for typical platforms".)

                    Comment

                    • Barry Schwarz

                      #11
                      Re: Problems with Pointers

                      On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), zaimoni@zaimoni .com wrote:
                      >On Sep 1, 2:55 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
                      >zaim...@zaimon i.com said:
                      >>
                      ><snip>
                      >>
                      In this case, it's a matter of coding style whether to use calloc or
                      malloc for doublePointer.
                      >>
                      >No, malloc is the better choice.
                      >
                      >As a correct implementation can be explicitly verified to never
                      >inspect the values in the malloc'd array in the first place, malloc is
                      >the objectively better choice; the implied memset call has no
                      >observable effect.
                      At the very least it wastes time. At the worst, it creates the false
                      impression that the pointers have been properly initialized.
                      >
                      >(Regardless of whatever style guidelines that are in force at a
                      >specific locale, and whether portability to platforms from the age of
                      >the computing dinosaurs where the binary representation of NULL is not
                      >all-zero-bits is a concern. Obviously, the following paragraph should
                      You really believe that there are no modern systems that can support
                      accessing location 0? Even when using C to write the operating
                      system?
                      >have been qualified with "for typical platforms".)
                      --
                      Remove del for email

                      Comment

                      • Barry Schwarz

                        #12
                        Re: Problems with Pointers

                        On Mon, 1 Sep 2008 00:42:34 -0700 (PDT), zaimoni@zaimoni .com wrote:
                        >On Aug 31, 10:00 pm, stevenr...@gmai l.com wrote:
                        >Hello All
                        >>
                        > My question mainly is how to use/reference Double Pointers? I am
                        >currently trying to understand what the meaning of a 'vector of
                        >pointers' means also? What I am trying to do is take a char array and
                        >break it up into words omitting the spaces. What needs to be noted is
                        >that I am trying to accomplish this only using char ** and char *.
                        >
                        >As a learning exercise: assume we don't #include <string.h?
                        >
                        >Therefore, I am creating it from scratch. Below is code that I have
                        >written so far:
                        >>
                        > int main()
                        > {
                        > char input[125] = " Hello World\0"
                        >
                        >\0 is mostly redundant here. The string literal will implicitly have
                        >a \0 character appended to its representation as an array of
                        >characters.
                        The literal, if it exists in the object module, will indeed have a
                        second '\0' appended to it. The array named input, however, will
                        consist of 11 characters followed by 114 '\0's independent of whether
                        there are any '\0's specified or implied in the initialization.

                        --
                        Remove del for email

                        Comment

                        • Chris Torek

                          #13
                          Re: Problems with Pointers

                          In article <A8adnSJj4L--BybVnZ2dnUVZ8uC dnZ2d@bt.com>
                          Richard Heathfield <rjh@see.sig.in validwrote:
                          >Let's start by counting the number of words in the input string ...
                          [which results in]
                          >size_t wc(const char *s)
                          >{
                          size_t count = 0;
                          int state = NOT_IN_WORD;
                          int space = 0;
                          while(*s != '\0')
                          {
                          space = isspace((unsign ed char)*s);
                          if(state == NOT_IN_WORD && !space)
                          {
                          ++count;
                          state = IN_WORD;
                          }
                          else if(state == IN_WORD && space)
                          {
                          state = NOT_IN_WORD;
                          }
                          ++s;
                          }
                          return count;
                          >}
                          >... now we'd like to point at them. ...
                          >Here, then, is a function to do that. Observe its similarities and
                          >differences with regard to wc() - which it itself calls, by the way:
                          >
                          >#include <stdlib.h>
                          >#include <assert.h>
                          >char **wl_build(char *s)
                          >{
                          int space = 0;
                          int state = 0;
                          size_t thisword = 0;
                          size_t wordcount = wc(s);
                          char **wl = malloc((wordcou nt + 1) * sizeof *wl);
                          if(wl != NULL)
                          {
                          while(*s != '\0')
                          {
                          space = isspace((unsign ed char)*s);
                          if(state == NOT_IN_WORD && !space)
                          {
                          wl[thisword++] = s;
                          state = IN_WORD;
                          }
                          else if(state == IN_WORD && space)
                          {
                          *s = '\0'; /* terminate the token */
                          state = NOT_IN_WORD;
                          }
                          ++s;
                          }
                          wl[thisword] = NULL; /* list is NULL-terminated */
                          }
                          assert(thisword == wordcount);
                          return wl;
                          >}
                          >
                          >The alternative to doing this whole state machine thing twice is to count
                          >and reallocate as we go. Possible, and microscopically faster, but perhaps
                          >more effort than we'd like to go to, and the code would be messier, harder
                          >to follow, and harder to maintain.
                          Given the similarities and differences, I would consider one other
                          tweak. Suppose we rewrite both wc() and wl_build() in terms of a
                          third function. This third function is passed a "word list pointer"
                          value, which may be given as NULL, as well as a string ("s" above)
                          to split up into words. It counts the words, and -- if and only
                          if the word-list-pointer is non-NULL -- records and breaks up the
                          words as well. This results in:

                          static int wc_and_optional ly_build(char *s, char **wl) {
                          size_t count = 0;
                          int state = NOT_IN_WORD;
                          int space = 0;

                          while (*s != '\0') {
                          space = isspace((unsign ed char)*s);
                          if (state == NOT_IN_WORD && !space) {
                          if (wl != NULL) /* record start of token */
                          wl[count] = s;
                          count++;
                          state = IN_WORD;
                          } else if (state == IN_WORD && space) {
                          if (wl != NULL)
                          *s = '\0'; /* terminate the token */
                          state = NOT_IN_WORD;
                          }
                          ++s;
                          }
                          return count;
                          }

                          (I have made this "static" as it is not intended to be used by
                          any callers other than the two we are about to supply.)

                          Now we can rewrite both wc() and wl_build() in terms of this third
                          function, which exposes a slight flaw or two:

                          size_t wc(const char *s) {
                          return wc_and_optional ly_build((char *)s, NULL);
                          }

                          char **wl_build(char *s) {
                          size_t wordcount = wc(s);
                          char **wl = malloc((wordcou nt + 1) * sizeof *wl);

                          if (wl != NULL) {
                          size_t repeat = wc_and_optional ly_build(s, wl);

                          assert(repeat == wordcount);
                          wl[repeat] = NULL;
                          }
                          return wl;
                          }

                          The first flaw is that we have to "cast away const" in wc(), because
                          wc_and_optional ly_build() *might* write to *s. It does not in fact
                          write to *s as long as we pass NULL as the second argument.

                          The second flaw (or perhaps non-flaw) is that this code does not
                          fail the assert() if the malloc() fails. Instead, this code has
                          wl_build() return NULL. Richard's version will fail the assert
                          (unless of course you turn on NDEBUG) for any non-empty word list
                          (because "wordcount" will be non-zero, but "thisword" will be 0).
                          >The creation of token copies allows us to leave the original string
                          >unmodified ...
                          and, if you use a third "base" function to "do the real work",
                          allows one to fix the first flaw.
                          --
                          In-Real-Life: Chris Torek, Wind River Systems
                          Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                          email: gmail (figure it out) http://web.torek.net/torek/index.html

                          Comment

                          • zaimoni@zaimoni.com

                            #14
                            Re: Problems with Pointers

                            On Sep 1, 2:14 pm, Barry Schwarz <schwa...@dqel. comwrote:
                            On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), zaim...@zaimoni .com wrote:
                            (Regardless of whatever style guidelines that are in force at a
                            specific locale, and whether portability to platforms from the age of
                            the computing dinosaurs where the binary representation of NULL is not
                            all-zero-bits is a concern. ....
                            >
                            You really believe that there are no modern systems that can support
                            accessing location 0?
                            Accessing location zero is different than compiling a program so that
                            some C entity actually has location zero. E.g., I'd expect location
                            zero to be accessible (with suitable privileges) in C on an Intel
                            platform simply because that's the start of the hardware interrupt
                            vector table. That doesn't mean a C variable or function could
                            actually be compiled to live there.

                            As for a compiler placing entities at location zero:
                            Extant? Sure, such systems exist and remain in use. They don't seem
                            to be very high on the porting priority list for the FSF, as the use
                            of calloc to NULL-initialize pointer arrays is explicitly approved in
                            their portability checklist.

                            Chronologically new design? I wouldn't be surprised at all, even
                            though I don't have an example "on tap".

                            Vaguely modern design? Theoretically possible -- but I'd be surprised
                            if an example actually existed.

                            Comment

                            • Richard Heathfield

                              #15
                              Re: Problems with Pointers

                              Chris Torek said:

                              <snip>
                              The second flaw (or perhaps non-flaw) is that this code does not
                              fail the assert() if the malloc() fails. Instead, this code has
                              wl_build() return NULL. Richard's version will fail the assert
                              (unless of course you turn on NDEBUG) for any non-empty word list
                              (because "wordcount" will be non-zero, but "thisword" will be 0).
                              I have to confess that the assert was in any case mere scaffolding, which I
                              ought to have removed before posting. I actually put it in for debugging
                              purposes, but this particular assertion has no business being in the final
                              code because it can be fired by a runtime resource shortage as well as by
                              a programming error. (The assertion helped me to find such an error, but
                              it was nevertheless the wrong tool for the job in this case.)

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

                              Working...