Help explain char * and char [] differences 
Author Message
 Help explain char * and char [] differences

I came across an interesting function strtok() which i find will be very
useful in parsing config files in my mini-game (yes, I'm that
inexperienced).  using the given example I wrote a simple test prog to
check out the function :

int main()
{
   const char delimiters[] = "[]";
   char *teststr = "[1]";    /***** notice this declaration *****/
   char *token;

   printf("%s\n", delimiters);
   printf("%s\n", teststr);

   token = strtok(teststr, delimiters);
   printf("%s\n", token);

   token = strtok(NULL, delimiters);
   printf("%s\n", token);

   return 1;

Quote:
}

It gave a core dump.  When I looked back at the sample, I found the
string to be "stripped" is declared as char [] instead of char *.  sure
enough changing my declaration to char teststr[] worked.

I thought char * is the same as char[]?  It's not that I needed
preallocated space by putting teststr[512] or something. I looked up the
text bk & sure enough char * is more flexible than char [], & strtok()
takes in a char * anyway.  any comments why only a char [] works here?

I also have another query : how do I reset a char * back to the 1st char
in the string when I've done ++ operations to the pointer?  there's no
way, and I'll need a 2nd ptr to point to the head, much like a linked
list, right?

thanx for the enlightenment,
Aaron



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences


Quote:
> I came across an interesting function strtok() which i find will be
very
> useful in parsing config files in my mini-game (yes, I'm that
> inexperienced).  using the given example I wrote a simple test prog to
> check out the function :

> int main()
> {
>    const char delimiters[] = "[]";
>    char *teststr = "[1]";    /***** notice this declaration *****/
>    char *token;

>    printf("%s\n", delimiters);
>    printf("%s\n", teststr);

>    token = strtok(teststr, delimiters);
>    printf("%s\n", token);

>    token = strtok(NULL, delimiters);
>    printf("%s\n", token);

>    return 1;
> }

> It gave a core dump.  When I looked back at the sample, I found the
> string to be "stripped" is declared as char [] instead of char *.
sure
> enough changing my declaration to char teststr[] worked.

> I thought char * is the same as char[]?

     No, it is not. If your book doesn't explain this, dump the
book. In any case, read the FAQ at
    http://www.eskimo.com/~scs/C-faq/top.html
- it is explained there in details.

Quote:
> It's not that I needed
> preallocated space by putting teststr[512] or something.

   No, pointer is valid, but it points to a string literal.

Quote:
> I looked up the
> text bk & sure enough char * is more flexible than char [], & strtok()
> takes in a char * anyway.  any comments why only a char [] works here?

    Because:
   a) strtok() modifies the string being passed to it;
   b) you are passing to it a pointer to a string literal;
and
   c) trying to modify string literal invokes undefined behaviour -
     in your specific case, segmentation fault.

--
        Regards,
                Alex Krol
Disclaimer: I'm not speaking for Scitex
Corporation Ltd

Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences


- snip -
Yes,
char *teststr;
and
char teststr[];
are different animals.

Question:  What does the (very simple) expression
teststr
mean, say when used as an argument value in a function call?
That was the source of confusion - but not of the core dump.
The name of an array, when appearing alone, is interpreted
as the value of a pointer to its first element, just as if you had
written  &teststr[0].

Note that your first declaration also makes some sense.
But the problem here is that the char array it points to is a
constant (unmodifiable).  And it will be modified by strtok().
That caused the core dump.  Luckily, since this is OS dependent.



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences


Quote:

> I thought char * is the same as char[]?  It's not that I needed
> preallocated space by putting teststr[512] or something. I looked up
the
> text bk & sure enough char * is more flexible than char [], & strtok()
> takes in a char * anyway.  any comments why only a char [] works here?

No, they're not the same.  One form declares a modifiable buffer, the
other simply sets a pointer to an unmodifiable location.

char *p = "hello";  /* p points to a location in unwritable memory */
char q[] = "world"; /* q is a static buffer, 6 chars long, and */
                    /* "world" is copied into it */

The problem is that strtok() modifies the buffer you are scanning,
replacing the delimiters with a '\0' character.  Passing a string
constant or a pointer to a string constant will cause it to choke.

t = strtok ("hello", "l"); /* bad */
t = strtok (p, "l"); /* bad */
t = strtok (q, "l"); /* ok */

Quote:
> I also have another query : how do I reset a char * back to the 1st
char
> in the string when I've done ++ operations to the pointer?  there's no
> way, and I'll need a 2nd ptr to point to the head, much like a linked
> list, right?

Yes.  You'll need to preserve the original address somehow.

There's one other thing you'll need to watch out for when using
strtok().  You can't nest calls -- that is, you can't read one token,
then parse it, then try to read from the original string again.  Here's
an example (error checking omitted for brevity):

void get_date_tokens(char *buf, char *delim, char *m, char *d, char *y)
{
    m = strtok (buf, delim);
    d = strtok (NULL, delim);
    y = strtok (NULL, delim);

Quote:
}

void get_time_tokens(char *buf, char *delim, char *h, char *m)
{
    h = strtok (buf, delim);
    m = strtok (NULL, delim);

Quote:
}

int main (void)
{
    char date[] = "09/13/1999 09:43";
    char *bufd, *buft;
    char *m, *d, *y, *H, *M;

    /*
    ** The following code won't work properly.  Calls to
    ** strtok() cannot be nested.
    ** After calling get_date_tokens, we will have lost our original
    ** place in the date buffer.
    */
    bufd = strtok (date, " ");
    get_date_tokens (bufd, "/", m, d, y);
    buft = strtok (NULL, " ");
    get_time_tokens (buft, ":", H, M);

    /*
    ** This is the proper way to handle the problem.  You fully parse
    ** the original string first, *then* work on each part of it.
    */
    bufd = strtok (date, " ");
    buft = strtok (NULL, " ");
    get_date_tokens (bufd, "/", m, d, y);
    get_time_tokens (buft, ":", H, M);

Quote:
}
> thanx for the enlightenment,
> Aaron

--
Phrases often heard just before a major disaster:
  "How hard can it be?"
  "Hey, watch this!"
  "Don't worry, this time I *know* what I'm doing..."

Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences
Aaron Seet schrieb:

Quote:

> I came across an interesting function strtok() which i find will be very
> useful in parsing config files in my mini-game (yes, I'm that
> inexperienced).  using the given example I wrote a simple test prog to
> check out the function :

> int main()
> {
>    const char delimiters[] = "[]";
>    char *teststr = "[1]";    /***** notice this declaration *****/
>    char *token;

>    printf("%s\n", delimiters);
>    printf("%s\n", teststr);

>    token = strtok(teststr, delimiters);

Hi Aaron Seet,

As you have noticed yourself (below) the "char *teststr" causes Undefined
Behaviour (in the form of a "core dump") in the call to "strtok()". That's
because "strtok()" is defined to modify the given source string. But a
string literal is read-only, which means that you are not allowed to
modify it. Changing the declaration like this:
    char teststr[] = "[1]";
places (copies) the string literal into a local variable.

Quote:
>    printf("%s\n", token);

>    token = strtok(NULL, delimiters);
>    printf("%s\n", token);

The above line is another bug that you have overlooked. The return value
of "strtok()" is NULL if no more token were found. Since your test string
does not have a valid second token your are passing NULL to "printf()" and
that causes Undefined Behaviour. Your specific "printf()" implementation
might detect this and handle it in a non destructive way, but you must not
depend on this.

Quote:
>    return 1;

And one final portability tip: according to the ANSI-C standard there are
only three valid return values for main: 0, EXIT_SUCCESS and EXIT_FAILURE.
The later two are defined in <stdlib.h>.

Quote:
> I thought char * is the same as char[]?

No, it is not. Not by a long run. The first one is a pointer without any
space allocated to it and the later is an array of a specific size. Even
this line is not identical to a real array:
   char *test = "some text";
For one thing it sets the pointer to a string literal, which is defined as
being read-only. For another "test" is still just a pointer, which has
subtle differences to an array.

I urge you to read the section 6 of the comp.lang.c FAQ, which explains
the differences between "Arrays and Pointers" in a very good and
understandable way, including several examples.

Quote:
> It's not that I needed
> preallocated space by putting teststr[512] or something.

Something like:
   char test[] = "some text";
will give and occupy just the space needed for storing the text and an
additional terminating zero byte.

For using "strtok()" you must supply modifiable memory. Either by
declaring a real array or by dynamically allocating the memory using
"malloc()".

Quote:
> I looked up the
> text bk & sure enough char * is more flexible than char [], & strtok()
> takes in a char * anyway.

Well, you can have a pointer point to an array, if you want to use pointer
arithmetic:
   char test[] = "some text";
   char *p;
   p = test;

The reason why "strtok()" (and any other string processing function) takes
a "char*" is explained in the FAQ. Please read that first, it should make
things clear. If it does not, feel free to ask here again.

Quote:
> I also have another query : how do I reset a char * back to the 1st char
> in the string when I've done ++ operations to the pointer?

By storing the original pointer separately. If the original is an array
you simply reassign the array:
  p = test;
(re)sets "p" to the first element of the array "test".

Quote:
> there's no
> way, and I'll need a 2nd ptr to point to the head, much like a linked
> list, right?

Sounds correct.

You can get the FAQ at http://www.eskimo.com/~scs/C-faq/top.html or
at ftp://rtfm.mit.edu/pub/usenet/comp.lang.c/C-FAQ-list and it gets
posted to this newsgroup and to news.answers regularly (at the
beginning of each month).

Stephan
(initiator of the campaign against grumpiness in c.l.c)



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:
> I thought char * is the same as char[]?

No, one is modifiable ([]), the other is not (*).

Quote:
> I also have another query : how do I reset a char * back to the 1st char
> in the string when I've done ++ operations to the pointer?

Simpler to save a copy of the original.

--

Paul Lutus
www.arachnoid.com


Quote:
> I came across an interesting function strtok() which i find will be very
> useful in parsing config files in my mini-game (yes, I'm that
> inexperienced).  using the given example I wrote a simple test prog to
> check out the function :

> int main()
> {
>    const char delimiters[] = "[]";
>    char *teststr = "[1]";    /***** notice this declaration *****/
>    char *token;

>    printf("%s\n", delimiters);
>    printf("%s\n", teststr);

>    token = strtok(teststr, delimiters);
>    printf("%s\n", token);

>    token = strtok(NULL, delimiters);
>    printf("%s\n", token);

>    return 1;
> }

> It gave a core dump.  When I looked back at the sample, I found the
> string to be "stripped" is declared as char [] instead of char *.  sure
> enough changing my declaration to char teststr[] worked.

> I thought char * is the same as char[]?  It's not that I needed
> preallocated space by putting teststr[512] or something. I looked up the
> text bk & sure enough char * is more flexible than char [], & strtok()
> takes in a char * anyway.  any comments why only a char [] works here?

> I also have another query : how do I reset a char * back to the 1st char
> in the string when I've done ++ operations to the pointer?  there's no
> way, and I'll need a 2nd ptr to point to the head, much like a linked
> list, right?

> thanx for the enlightenment,
> Aaron



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:

> I also have another query : how do I reset a char * back to the 1st char
> in the string when I've done ++ operations to the pointer?

Just as you can point to the next element using the increment
operator(s), you can go an element back using the decement operators.
Here's an example:

char *myPtr;
char myArray[] = "Hello!";

myPtr = myArray;        /* myPtr points to myArray[0], which is 'H' */
myPtr++;                /* myPtr points to myArray[1], which is 'e' */
myPtr--;                /* myPtr points back to myArray[0] */

--
_________________________________
Jordan Katz



Fri, 01 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences
I had this misconception a char * string would be modifiable since I did
not explicity declare using const.  So its const by default.

I'll stick to arrays then.
Thanks for the clarifications!

Aaron

PS - yea, I'm having real weird probs with my news server? I posted the
1st msg but didn't see any update for a day or so & thought it got
lost.  It only appeared after I posted the 2nd, which also took a few
hrs to appear, even when other posts were coming thru.  And it appeared
both appeared at my face at the same time!  Is it my side or my news
server or the newsgrp host????



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:

>> I also have another query : how do I reset a char * back to the 1st
>char
>> in the string when I've done ++ operations to the pointer?  there's no
>> way, and I'll need a 2nd ptr to point to the head, much like a linked
>> list, right?

>Yes.  You'll need to preserve the original address somehow.

Really? I didn't know this. I thought that a -- operations on the pointer
would eventually reset the char * to it's original position. I even tried
this out and it seemed to work. I guess this is just another one of those
strange ``undefined behaviour'' issues with C, or perhaps my compiler was
doing a bit of magic and I just got lucky? For what it's worth here's the
code I tried this with. Constructive criticism is VERY, VERY, VERY
welcome. :-)

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

void foo(char *s1, char *s2)
{
        while ((*s2++ = *s1++) != '\0')
                ;
         --s1;
        if (*--s1 == 't')
                printf("This is only a test.\n");

Quote:
}

This code isn't meant to do anything spectacular nor is it supposed to
look good. :-)

Anyway, I guess the above code is both dangerous and wrong? Thanks folks.

--
Bishop



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:
> >Yes.  You'll need to preserve the original address somehow.

> Really? I didn't know this. I thought that a -- operations on the pointer
> would eventually reset the char * to it's original position.

But don't you see -- your method doesn't contradict John's statement. You
did preserve the original address by storing the number of decrements
required to restore the original address.

--

Paul Lutus
www.arachnoid.com


<snip>



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:

>> >Yes.  You'll need to preserve the original address somehow.

>> Really? I didn't know this. I thought that a -- operations on the pointer
>> would eventually reset the char * to it's original position.

>But don't you see -- your method doesn't contradict John's statement. You
>did preserve the original address by storing the number of decrements
>required to restore the original address.

>--

>Paul Lutus
>www.arachnoid.com

I suppose you are right. Stupid me. How about my next example? It seems to
do what is asked of it. Can it also be considered correct?

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

int main()
{
        char    *p;

        p = malloc(6 * sizeof *p);
        if (p == NULL) {
                fprintf(stderr, "FATAL: out of memory.\n");
                exit(EXIT_FAILURE);
        strcpy(p, "hello");
        printf("%s\n", ++p);
        printf("%s\n", ++p);
        printf("%s\n", --p);
        printf("%s\n", --p);

        return EXIT_SUCCESS;

Quote:
}

--
Bishop


Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:
> I suppose you are right. Stupid me. How about my next example? It seems to
> do what is asked of it. Can it also be considered correct?

All except the part where it doesn't call free(). If you say, "But the
return from main() frees the allocation," this is generally true but it is
bad practice to depend on it.

Also your code is uncompilable -- a missing brace. Always copy your code
directly from your program editor, never just type it in.

Also your program uses exit() in one path, which will not deallocate the
malloc'd memory.

--

Paul Lutus
www.arachnoid.com


Quote:

> >> >Yes.  You'll need to preserve the original address somehow.

> >> Really? I didn't know this. I thought that a -- operations on the
pointer
> >> would eventually reset the char * to it's original position.

> >But don't you see -- your method doesn't contradict John's statement. You
> >did preserve the original address by storing the number of decrements
> >required to restore the original address.

> >--

> >Paul Lutus
> >www.arachnoid.com

> I suppose you are right. Stupid me. How about my next example? It seems to
> do what is asked of it. Can it also be considered correct?

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

> int main()
> {
>         char    *p;

>         p = malloc(6 * sizeof *p);
>         if (p == NULL) {
>                 fprintf(stderr, "FATAL: out of memory.\n");
>                 exit(EXIT_FAILURE);
>         strcpy(p, "hello");
>         printf("%s\n", ++p);
>         printf("%s\n", ++p);
>         printf("%s\n", --p);
>         printf("%s\n", --p);

>         return EXIT_SUCCESS;
> }

> --
> Bishop



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences
Thanks again. I wrongly accepted at face value another thread that asserted
a different outcome for exit().

--

Paul Lutus
www.arachnoid.com


Quote:


> > > I suppose you are right. Stupid me. How about my next example? It
seems
> to
> > > do what is asked of it. Can it also be considered correct?

> > All except the part where it doesn't call free(). If you say, "But the
> > return from main() frees the allocation," this is generally true but it
> is
> > bad practice to depend on it.

> > Also your code is uncompilable -- a missing brace. Always copy your code
> > directly from your program editor, never just type it in.

> > Also your program uses exit() in one path, which will not deallocate the
> > malloc'd memory.

>        5.1.2.2.3  Program termination

>        [#1]  If  the  return  type  of  the main function is a type
>        compatible with int, a return from the initial call  to  the
>        main  function  is  equivalent  to calling the exit function
>        with  the  value  returned  by  the  main  function  as  its
>        argument;9) reaching the } that terminates the main function
>        returns  a value of 0.  If the return type is not compatible
>        with int,  the  termination  status  returned  to  the  host
>        environment is unspecified.

> That's from C9X, I'm afraid - no C89 here.

> Anyway, the point is that if return from main() frees the memory, so does
> exit().

> I do agree, though, that it's good programming practice to wash your own
> dishes.

> --
> Richard Heathfield

> "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences

Quote:


> >> >Yes.  You'll need to preserve the original address somehow.

> >> Really? I didn't know this. I thought that a -- operations on the pointer
> >> would eventually reset the char * to it's original position.

> >But don't you see -- your method doesn't contradict John's statement. You
> >did preserve the original address by storing the number of decrements
> >required to restore the original address.
> I suppose you are right. Stupid me. How about my next example? It seems to
> do what is asked of it. Can it also be considered correct?

Clearly not.  #include is misspelled, a closing '}' is missing, and you
never free the allocated memory.  Try running this:

#include <stdio.h>                                          /* mha */
#include <stdlib.h>
#include <string.h>

int main()
{
    char *p;

    p = malloc(6 * sizeof *p);
    if (p == NULL) {
        fprintf(stderr, "FATAL: out of memory.\n");
        exit(EXIT_FAILURE);
    }                           /* mha */
    printf("After %s, p is %p\n", "allocaton", (void *)p);  /* mha */
    strcpy(p, "hello");
    printf("After %s, p is %p\n", "strcpy", (void *)p);     /* mha */
    printf("%s\n", ++p);
    printf("After %s, p is %p\n", "first ++p", (void *)p);  /* mha */
    printf("%s\n", ++p);
    printf("After %s, p is %p\n", "second ++p", (void *)p);     /* mha
*/
    printf("%s\n", --p);
    printf("After %s, p is %p\n", "first --p", (void *)p);  /* mha */
    printf("%s\n", --p);
    printf("After %s, p is %p\n", "second --p", (void *)p);     /* mha
*/
    free(p);                    /* mha */

    return EXIT_SUCCESS;

Quote:
}

[Output with one impementation, yours will vary]
After allocaton, p is 8f0d0
After strcpy, p is 8f0d0
ello
After first ++p, p is 8f0d1
llo
After second ++p, p is 8f0d2
ello
After first --p, p is 8f0d1
hello
After second --p, p is 8f0d0

Quote:

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

> int main()
> {
>         char    *p;

>         p = malloc(6 * sizeof *p);
>         if (p == NULL) {
>                 fprintf(stderr, "FATAL: out of memory.\n");
>                 exit(EXIT_FAILURE);
>         strcpy(p, "hello");
>         printf("%s\n", ++p);
>         printf("%s\n", ++p);
>         printf("%s\n", --p);
>         printf("%s\n", --p);

>         return EXIT_SUCCESS;
> }

> --
> Bishop

--

__________________________________________________________
Fight spam now!
Get your free anti-spam service: http://www.brightmail.com



Sat, 02 Mar 2002 03:00:00 GMT  
 Help explain char * and char [] differences


Quote:
> > I suppose you are right. Stupid me. How about my next example? It seems
to
> > do what is asked of it. Can it also be considered correct?

> All except the part where it doesn't call free(). If you say, "But the
> return from main() frees the allocation," this is generally true but it
is
> bad practice to depend on it.

> Also your code is uncompilable -- a missing brace. Always copy your code
> directly from your program editor, never just type it in.

> Also your program uses exit() in one path, which will not deallocate the
> malloc'd memory.

       5.1.2.2.3  Program termination

       [#1]  If  the  return  type  of  the main function is a type
       compatible with int, a return from the initial call  to  the
       main  function  is  equivalent  to calling the exit function
       with  the  value  returned  by  the  main  function  as  its
       argument;9) reaching the } that terminates the main function
       returns  a value of 0.  If the return type is not compatible
       with int,  the  termination  status  returned  to  the  host
       environment is unspecified.

That's from C9X, I'm afraid - no C89 here.

Anyway, the point is that if return from main() frees the memory, so does
exit().

I do agree, though, that it's good programming practice to wash your own
dishes.

--
Richard Heathfield

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.



Sun, 03 Mar 2002 03:00:00 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. Can someone explain whay char[] is compatible with char*

2. what is the difference between this types: char and System.Char

3. NewBie: difference between char* and unsigned char*

4. Difference between char* and char[]

5. Simpleton: Can someone tell me the difference between char* and char x[255]

6. what's differences between char [] and char* ?

7. Differences between char array[SIZE] and char *array

8. The differences between char * & char []

9. difference in space reserved between a char use[] and char *use

10. Difference between char and unsigned char

11. what's the difference between char * and const char *

12. What's the difference between char [][20] and char (*)[20]

 

 
Powered by phpBB® Forum Software