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

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

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

2. ### Ben BacarisseGuest

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

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

3. ### Barry SchwarzGuest

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;
>
> doublePointer = malloc(125 * sizeof(char *));

Do you really think you will need a char* for char in 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
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;

>
> > doublePointer = malloc(125 * sizeof(char *));

>
> Do you really think you will need a char* for char in 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

, Sep 1, 2008
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

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

>
> doublePointer = malloc(125 * sizeof(char *));

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' */
#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
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
8. ### Barry SchwarzGuest

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
9. ### Barry SchwarzGuest

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
10. ### Chris TorekGuest

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