Problems with Pointers

Discussion in 'C Programming' started by stevenruiz@gmail.com, Sep 1, 2008.

  1. Guest

    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(doublePointer);

    return 0;
    }

    Any hints and suggestions about the algorithm/design would be
    welcome. Thanks.
     
    , Sep 1, 2008
    #1
    1. Advertising

  2. 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(const 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(doublePointer);
    >
    > return 0;
    > }
    >
    > Any hints and suggestions about the algorithm/design would be
    > welcome. Thanks.


    --
    Ben.
     
    Ben Bacarisse, Sep 1, 2008
    #2
    1. Advertising

  3. On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), 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 is a char*. If you want doublePointer 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_of_elements_desired * sizeof *x);

    > }
    >
    >
    > free(doublePointer);


    If doublePointer and all the doublePointer point to allocated
    memory, the doublePointer need to be freed before you free
    doublePointer.

    >
    > return 0;
    >}


    --
    Remove del for email
     
    Barry Schwarz, Sep 1, 2008
    #3
  4. Guest

    On Aug 31, 10:57 pm, Barry Schwarz <> wrote:
    > On Sun, 31 Aug 2008 20:00:44 -0700 (PDT), 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 is a char*. If you want doublePointer 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_of_elements_desired * sizeof *x);
    >
    > > }

    >
    > > free(doublePointer);

    >
    > If doublePointer and all the doublePointer point to allocated
    > memory, the doublePointer 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.
     
    , Sep 1, 2008
    #4
  5. Guest

    On Sep 1, 12:46 am, 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.
     
    , Sep 1, 2008
    #5
  6. Guest

    On Aug 31, 10:00 pm, 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_strings 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_length+1); /* alternately,
    malloc((token_length+1)*sizeof(char)) to look like the other malloc */
    doublePointer[j][token_length+1] = '\0'; /* plain 0 also works in
    place of '\0' */
    strncpy(doublePointer[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.
     
    , Sep 1, 2008
    #6
  7. Guest

    On Sep 1, 2:55 am, Richard Heathfield <> wrote:
    > 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".)
     
    , Sep 1, 2008
    #7
  8. On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), wrote:

    >On Sep 1, 2:55 am, Richard Heathfield <> wrote:
    >> 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
     
    Barry Schwarz, Sep 1, 2008
    #8
  9. On Mon, 1 Sep 2008 00:42:34 -0700 (PDT), wrote:

    >On Aug 31, 10:00 pm, 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
     
    Barry Schwarz, Sep 1, 2008
    #9
  10. Chris Torek Guest

    In article <>
    Richard Heathfield <> wrote:
    >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((unsigned 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((wordcount + 1) * sizeof *wl);
    > if(wl != NULL)
    > {
    > while(*s != '\0')
    > {
    > space = isspace((unsigned 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_optionally_build(char *s, char **wl) {
    size_t count = 0;
    int state = NOT_IN_WORD;
    int space = 0;

    while (*s != '\0') {
    space = isspace((unsigned 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_optionally_build((char *)s, NULL);
    }

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

    if (wl != NULL) {
    size_t repeat = wc_and_optionally_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_optionally_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
     
    Chris Torek, Sep 1, 2008
    #10
  11. Guest

    On Sep 1, 2:14 pm, Barry Schwarz <> wrote:
    > On Mon, 1 Sep 2008 08:43:08 -0700 (PDT), 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.
     
    , Sep 1, 2008
    #11
    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. Phil
    Replies:
    1
    Views:
    671
    llewelly
    Sep 16, 2003
  2. muser
    Replies:
    3
    Views:
    784
    Ron Natalie
    Sep 18, 2003
  3. A
    Replies:
    3
    Views:
    481
    Alan Kelon
    Oct 29, 2003
  4. Xamalek
    Replies:
    7
    Views:
    708
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    737
Loading...

Share This Page