char[] and char * questions 
Author Message
 char[] and char * questions

hi, char * seem abit of an anomaly to me but maybe i've just got it all
wrong. As I understand it char[] is used as a mutable char sequence type
and char * are immutable. The problem I have with char * is that they
don't seem to obey the standard pointer type operations. They don't need
to be malloced (thankfully!) and they are not derefernced to access the
string contents. Being new to C I just want to make sure that I'm
understanding these types correctly. Do I have a correct approach to
copying a char[] to char * in the code following (ie: make_string).
thanks for helping.

#include <stdio.h>

#define MAXSIZE 20

int read_text(char text[], int size);
void make_string(char *string, char *text);

int main()
{
    int count = 0;
    char* text[MAXSIZE];
    char *string;
    count = read_text(text, MAXSIZE);
    printf("TEXT: %s\nCOUNT: %i\n", text, count);
    make_string(string, &text);
    printf("STRING: %s\t%p\n", string, &string);
    return 0;

Quote:
}

int read_text(char text[], int size)
{
    int count, input;
    for (count=0; count < (size-1) &&(input = getchar()) != EOF && input
!= '\n'; ++count)
        text[count] = input;
    text[count++] = '\0';
    return count;

Quote:
}

void make_string(char *string, char *text)
{
    while((*string++ = *text++))
        ;
Quote:
}



Sat, 12 Feb 2005 11:29:34 GMT  
 char[] and char * questions
On Tue, 27 Aug 2002 15:29:34 +1200, Matthew

Quote:

>hi, char * seem abit of an anomaly to me but maybe i've just got it all
>wrong. As I understand it char[] is used as a mutable char sequence type
>and char * are immutable. The problem I have with char * is that they
>don't seem to obey the standard pointer type operations. They don't need
>to be malloced (thankfully!) and they are not derefernced to access the
>string contents. Being new to C I just want to make sure that I'm
>understanding these types correctly. Do I have a correct approach to
>copying a char[] to char * in the code following (ie: make_string).
>thanks for helping.

Sorry, you're not even close. Don't worry, I made a similar mistake
(and I think most people do).

I'm not sure what you mean by mutable and immutable, but a char[]
(array of char) always has the same length - the length you declare it
with. This length can be retrieved using the sizeof operator (except,
I believe, in the case of a VLA).

Now, an array of char can be a nice place to store a string, but the
two things are not the same. A string is a sequence of chars that ends
with a null character (a char with the value 0, usually written as
'\0' to emphasize that it's being used as a string terminator). You
can store a string into an array of char as long as there is enough
room in the array for the entire string plus the null terminator. If
an array of char contains a string, sizeof will still give the total
number of elements in the char array, while strlen() will give the
number of chars in the string contained in the array. For an array A
with a string stored in it, strlen(A) < sizeof(A) must be true. To
store a string into an array, you may do something like this:

char array[200];
strcpy(array, "This is a string");

or you can initialize it with a string:

char array[] = "This is a string used as an initializer";

The size of the array is determined by the compiler in this case (it
will be just large enough for the initial string including the null
terminator).

A char * (pointer to char) is completely different. You cannot store a
string in a pointer to char. It can only store the address of a char.
It's possible that this char may be the first char in a string, but
not necessary.

You *cannot* do this:

char *cp;
strcpy(cp, "This is completely broken!!!");

Because cp doesn't point to anything useful yet. In fact, you don't
know where it points - it could point to some critical area of memory
that causes bad things to happen when it's overwritten. However, you
could do this:

char *cp;
char array[200];
cp = array; /* cp now points to the first element of array */
strcpy(cp, "This is alright");

This has the exact same effect as if the first argument to strcpy was
array instead of cp.

So, you said that char *s don't need to be malloced. Presumably, you
meant that they don't need to be assigned a return value from malloc.
This is true, but it is equally true of all pointer types. You may
make them point to memory you got some other way (such as declaring a
local variable). However, it's very common to use them to point to
memory returned from a malloc call. The main advantage to this is that
you can get the memory without knowing at compile time how much you
want. For example, I may do this:

char *make_new_string(const char *src)
{
    char *dest;
    size_t len = strlen(src);
    dest = malloc((len+1) * sizeof(*dest)); /* sizeof(*dest) is
redundant as long as dest is a char *, but it can't hurt. */
    if (dest != NULL)
    {
        char *temp = dest;
        while (*temp++ = *src++) { /* do nothing */ }
    }
    return dest;

Quote:
}

This function does what I think you were trying to do in your
make_string function. Many C implementations include a function that
does the same thing called strdup(). This is not a standard function
however, and the name of it violates a reserved namespace ("str"
followed by a lower case letter is reserved for future use by the
standard), so if you make your own version don't use that name
(dupstr() is the usual replacement).

You also said that char *s are not dereferenced to access the string
contents. Pointers to char can be dereferenced in exactly the same way
as any other pointer, by placing the * operator in front of it. They
can use pointer arithmetic just like any other pointer. And they can
be dereferenced using array notation just like other pointers. There's
nothing special or magical about them beyond what any other pointer
type can do.

-Kevin



Sat, 12 Feb 2005 12:03:01 GMT  
 char[] and char * questions
On Tue, 27 Aug 2002 15:29:34 +1200, Matthew

Quote:

>hi, char * seem abit of an anomaly to me but maybe i've just got it all
>wrong. As I understand it char[] is used as a mutable char sequence type
>and char * are immutable. The problem I have with char * is that they

Whether or not the data the char* points to can be changed depends on
what it points to.  It is not a property of the pointer.   Consider

        char *p1 = "abcde";
        char a1[] = "abcde";
        char *p2 = a1;

p1 and p2 point to equal strings.  None of the data pointed to by p1
can be changed while any of the data pointed to by p2 can be.

Quote:
>don't seem to obey the standard pointer type operations. They don't need
>to be malloced (thankfully!) and they are not derefernced to access the

Whether you assign a char* the address of a defined character or the
space allocated by malloc is strictly a function of program design.
This is not unique to char* but applies to any pointer in your
program.  No pointer *needs* to be malloced.

Quote:
>string contents. Being new to C I just want to make sure that I'm

Since a string is a sequence of characters that start at the address
you specify and continue until you reach a '\0', you don't dereference
the pointer to refer to it.  (Similarly, if the string is in a defined
array, then you would not subscript the array name to refer to the
string.)  The following produce the same result:

        printf("%s\n", p1);
        printf("%s\n", p2);
        printf("%s\n", a1);

If you want to refer to the individual character the pointer points
to, you would definitely dereference it.

Quote:
>understanding these types correctly. Do I have a correct approach to
>copying a char[] to char * in the code following (ie: make_string).
>thanks for helping.

>#include <stdio.h>

>#define MAXSIZE 20

>int read_text(char text[], int size);
>void make_string(char *string, char *text);

>int main()
>{
>    int count = 0;
>    char* text[MAXSIZE];
>    char *string;
>    count = read_text(text, MAXSIZE);

You obviously didn't try to compile this.  The first parameter to
read_text is an array of char.  The first argument in your function
call is an array of char*.  These are not compatible types.

Quote:
>    printf("TEXT: %s\nCOUNT: %i\n", text, count);

This invokes undefined behavior.  The %s format requires the
corresponding argument to be char*.  You are passing a char**.

Quote:
>    make_string(string, &text);

Multiple problems here:

        string is an uninitialized pointer.  Passing an uninitialized
value to a function invokes undefined behavior.

        The 2nd parameter in make_string is a char*.  Your argument in the
function call is the address of an array of char*.  It has type
char*(*)[MAXSIZE], which reads in English as "pointer to array of
MAXSIZE pointer to char."

Notice that both read_text and make_string are expecting char*.  In
one you pass text and in another you pass &text.  Neither one is
correct but if one had been, then the other couldn't be.

Quote:
>    printf("STRING: %s\t%p\n", string, &string);

More undefined behavior:

        string is still uninitialized so you can't pass its value to
printf.  (Remember C passes by value so make_string cannot change the
contents of string even though it can change the contents of what
string points to.)

        The %p format specifier requires the corresponding value to be a
void*.  It is true that char* and void* must be the same size and have
the same representation but you should still cast the argument.
(Consider a hardware implementation where void* is passed in a
different register than char*.)

- Show quoted text -

Quote:
>    return 0;
>}

>int read_text(char text[], int size)
>{
>    int count, input;
>    for (count=0; count < (size-1) &&(input = getchar()) != EOF && input
>!= '\n'; ++count)
>        text[count] = input;
>    text[count++] = '\0';
>    return count;
>}

>void make_string(char *string, char *text)
>{
>    while((*string++ = *text++))

Why double parentheses?

Quote:
>        ;
>}

<<Remove the del for email>>


Sat, 12 Feb 2005 12:49:07 GMT  
 char[] and char * questions

Quote:

> >void make_string(char *string, char *text)
> >{
> >    while((*string++ = *text++))

Barry Schwarz replied:

Quote:
> Why double parentheses?

Usually to stop a compiler warning about a possible error in the code, ie.
"=" vs "==". Some compilers need even stronger coercion:

while((*string++ = *text++) != 0)

--
Simon.



Sat, 12 Feb 2005 13:44:47 GMT  
 char[] and char * questions
THANKS for all the huge responses. I really appreciate the time you guys
have taken to help me out. matthew.


Sat, 12 Feb 2005 14:16:13 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. A char pointer (char *) vs. char array question

2. Converting char array of literals chars to escape chars

3. char *c,char c[ ] and char *c[ ]

4. char, unsigned char, signed char

5. char* -> char (newbie question)

6. a char and unsigned char question again

7. char* <> char* question

8. (THE simplest question ever) char[] when the required argument is a char *

9. question: char* lltostr(long long, char*)?

10. char* -> char (newbie question)

11. Question: extern char * versus extern char[]

12. char *,char[],&,Question

 

 
Powered by phpBB® Forum Software