Array of structs with strings

  • Follow


In C I have seen the idiom

char *name = "Tweety";

and have been assured that it is legit. However I have doubts about
the string assignments in the example below I found on the net. Are
these string assignments valid?

Thanks

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <stdio.h>

typedef struct robot ROBOT;

struct robot {
  char *name;
  int energy;
};

int main() {
  int i;

  ROBOT robots[3];

  robots[0].name = "Lunar Lee";
  robots[0].energy = 50;
  robots[1].name = "Planetary Pete";
  robots[1].energy = 20;

....
0
Reply goodTweetieBird (53) 3/21/2008 2:25:31 AM

goodTweetieBird wrote:
> In C I have seen the idiom
> 
> char *name = "Tweety";
> 
> and have been assured that it is legit. However I have doubts about
> the string assignments in the example below I found on the net. Are
> these string assignments valid?
> 
> Thanks
> 
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> #include <stdio.h>
> 
> typedef struct robot ROBOT;
> 
> struct robot {
>   char *name;
>   int energy;
> };
> 
> int main() {
>   int i;
> 
>   ROBOT robots[3];
> 
>   robots[0].name = "Lunar Lee";
>   robots[0].energy = 50;
>   robots[1].name = "Planetary Pete";
>   robots[1].energy = 20;

     Yes, they are valid.  `robots[n].name' is a char*
(for n == 0,1,2), just as `name' is, so anything you
can do with `name' can also be done with `robots[n].name'.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid
0
Reply esosman2 (2945) 3/21/2008 2:35:48 AM


>      Yes, they are valid.  `robots[n].name' is a char*
> (for n == 0,1,2), just as `name' is, so anything you
> can do with `name' can also be done with `robots[n].name'.
>
> --
> Eric Sosman
> esos...@ieee-dot-org.invalid

Thanks for posting but I do not see how it can be valid.
robots[0].name is only a pointer which I thought meant that it is a
few bytes in length. Seems it would soon be writing in unknown areas.

gtb
0
Reply goodTweetieBird (53) 3/21/2008 2:51:47 AM

On Mar 20, 9:51=A0pm, goodTweetieBird <goodTweetieB...@hotmail.com>
wrote:
> > =A0 =A0 =A0Yes, they are valid. =A0`robots[n].name' is a char*
> > (for n =3D=3D 0,1,2), just as `name' is, so anything you
> > can do with `name' can also be done with `robots[n].name'.
>
> > --
> > Eric Sosman
> > esos...@ieee-dot-org.invalid
>
> Thanks for posting but I do not see how it can be valid.
> robots[0].name is only a pointer which I thought meant that it is a
> few bytes in length. Seems it would soon be writing in unknown areas.
>
> gtb

That's very true. Try taking some rather long input and storing it in
robots[0].name. That way, even the best of compilers can't guess how
much memory should be allocated for robots[0].name to allow for
robots[1].name and robots[2].name. After that, output it, and you can
usually find that robots[1].name and robots[2].name are overwritten.

This is the reason for the malloc() function found in <stdlib.h> -
dynamic memory allocation. You don't know how long it is supposed to
be when you code, so you leave it as a char pointer, which can be
thought of as an array of undeclared length. At run-time, you find out
how long it is supposed to be and you use malloc() to allocate enough
space for the string. When you are done with it, you then free() it.
One very important thing to remember is to use free() to deallocate
the memory when you're finished with the string. Otherwise, you can
end up with a memory leak. The same is true for the calloc() and
realloc() functions - free() them when you're done!
0
Reply rpgfan3233 (7) 3/21/2008 3:06:09 AM

>
> That's very true. Try taking some rather long input and storing it in
> robots[0].name. That way, even the best of compilers can't guess how
> much memory should be allocated for robots[0].name to allow for
> robots[1].name and robots[2].name. After that, output it, and you can
> usually find that robots[1].name and robots[2].name are overwritten.
>
> This is the reason for the malloc() function found in <stdlib.h> -
> dynamic memory allocation. You don't know how long it is supposed to
> be when you code, so you leave it as a char pointer, which can be
> thought of as an array of undeclared length. At run-time, you find out
> how long it is supposed to be and you use malloc() to allocate enough
> space for the string. When you are done with it, you then free() it.
> One very important thing to remember is to use free() to deallocate
> the memory when you're finished with the string. Otherwise, you can
> end up with a memory leak. The same is true for the calloc() and
> realloc() functions - free() them when you're done!

Sounds like a source of subtle errors.

Thanx,

gtb
0
Reply goodTweetieBird (53) 3/21/2008 3:10:43 AM

goodTweetieBird wrote:
>>      Yes, they are valid.  `robots[n].name' is a char*
>> (for n == 0,1,2), just as `name' is, so anything you
>> can do with `name' can also be done with `robots[n].name'.
> 
> Thanks for posting but I do not see how it can be valid.
> robots[0].name is only a pointer which I thought meant that it is a
> few bytes in length. Seems it would soon be writing in unknown areas.

     robots[0].name is a pointer, a char* that can point to
any char anywhere.  That char may be the first of a string
of any length whatever; the char* just points to the first
char of the string.  It makes no difference how long the
string is; the char* just points to its beginning.

     char *name1 = "Peter";
     char *name2 = "Linus";
     char *name3 = "Anacletus";
     char *name4 = "Clement I";
     char *name5 = "Evaristus";
     ...

It doesn't matter how long the string themselves are; the
pointers work the same way anyhow.  The pointer name1 points
to P, name2 points to L, and so on, regardless of what comes
after those pointed-to chars.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid
0
Reply esosman2 (2945) 3/21/2008 3:16:16 AM

rpgfan3233 wrote:

> On Mar 20, 9:51�pm, goodTweetieBird <goodTweetieB...@hotmail.com>
> wrote:
>> > Yes, they are valid. �`robots[n].name' is a char*
>> > (for n == 0,1,2), just as `name' is, so anything you
>> > can do with `name' can also be done with `robots[n].name'.
>>
>> > --
>> > Eric Sosman
>> > esos...@ieee-dot-org.invalid
>>
>> Thanks for posting but I do not see how it can be valid.
>> robots[0].name is only a pointer which I thought meant that it is a
>> few bytes in length. Seems it would soon be writing in unknown areas.
>>
>> gtb
> 
> That's very true. Try taking some rather long input and storing it in
> robots[0].name. That way, even the best of compilers can't guess how
> much memory should be allocated for robots[0].name to allow for
> robots[1].name and robots[2].name. After that, output it, and you can
> usually find that robots[1].name and robots[2].name are overwritten.

This is false. robots[n].name are all of type char *. They can point to
the start of a char or an array of char. In C the construct "whatever"
is called a "string literal". What it does is effectively tell the
compiler to set aside some unnamed array of char big enough to hold the
string "whatever" and a terminating null character. The string literal
in an expression context evaluates to a value of type char *, which is
what you are assigning to robots[n].name. Storage is automatically
allocated for the string literals elsewhere and no memory overwrite
takes place.

> This is the reason for the malloc() function found in <stdlib.h> -
> dynamic memory allocation. You don't know how long it is supposed to
> be when you code,

In the case of a string literal, you do.

> so you leave it as a char pointer, which can be 
> thought of as an array of undeclared length.

No.

> At run-time, you find out 
> how long it is supposed to be and you use malloc() to allocate enough
> space for the string. When you are done with it, you then free() it.
> One very important thing to remember is to use free() to deallocate
> the memory when you're finished with the string. Otherwise, you can
> end up with a memory leak. The same is true for the calloc() and
> realloc() functions - free() them when you're done!

You cannot "free" the space taken by a string literal. However not all
strings are string literals. The following are valid constructs:

  char *str = "hello";
  char arr[] = "hello";
  char arr1[2] = "hello";
  char arr2[10] = "hello";
  char *ptr = malloc(strlen("hello") + 1);
    if (ptr) strcpy(ptr, "hello");
    else error();

This is where a memory overwrite occurs:

  char *ptr;
  strcpy(ptr, "hello");

0
Reply santosh.k83 (3969) 3/21/2008 3:52:26 AM

Eric Sosman wrote:
> goodTweetieBird wrote:
>
>> In C I have seen the idiom
>>
>> char *name = "Tweety";
>>
>> and have been assured that it is legit. However I have doubts about
>> the string assignments in the example below I found on the net. Are
>> these string assignments valid?
>>
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> #include <stdio.h>
>>
>> typedef struct robot ROBOT;
>>
>> struct robot {
>>   char *name;
>>   int energy;
>> };
>>
>> int main() {
>>   int i;
>>
>>   ROBOT robots[3];
>>
>>   robots[0].name = "Lunar Lee";
>>   robots[0].energy = 50;
>>   robots[1].name = "Planetary Pete";
>>   robots[1].energy = 20;
> 
>      Yes, they are valid.  `robots[n].name' is a char*
> (for n == 0,1,2), just as `name' is, so anything you
> can do with `name' can also be done with `robots[n].name'.

You have set the pointer for name to point to a non-writable
constant char. string.  So you can't diddle the names.  They are
just there.  However, you can replace them.

-- 
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: <http://cbfalconer.home.att.net>
            Try the download section.


-- 
Posted via a free Usenet account from http://www.teranews.com

0
Reply cbfalconer (19183) 3/21/2008 3:52:37 AM

santosh wrote:
> 
.... snip ...
> 
> This is where a memory overwrite occurs:
> 
>   char *ptr;
>   strcpy(ptr, "hello");

No it doesn't. It just blows up, because ptr was never initialized.

-- 
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: <http://cbfalconer.home.att.net>
            Try the download section.


-- 
Posted via a free Usenet account from http://www.teranews.com

0
Reply cbfalconer (19183) 3/21/2008 4:06:31 AM

goodTweetieBird <goodTweetieBird@hotmail.com> writes:
> In C I have seen the idiom
>
> char *name = "Tweety";
>
> and have been assured that it is legit. However I have doubts about
> the string assignments in the example below I found on the net. Are
> these string assignments valid?
>
> Thanks
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> #include <stdio.h>
>
> typedef struct robot ROBOT;
>
> struct robot {
>   char *name;
>   int energy;
> };
>
> int main() {
>   int i;
>
>   ROBOT robots[3];
>
>   robots[0].name = "Lunar Lee";
>   robots[0].energy = 50;
>   robots[1].name = "Planetary Pete";
>   robots[1].energy = 20;
>
> ...

Yes.

The comp.lang.c FAQ is at <http://www.c-faq.com/>.  See question 1.32
and all of section 6.

-- 
Keith Thompson (The_Other_Keith) <kst-u@mib.org>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Reply kst-u (21469) 3/21/2008 5:30:09 AM

CBFalconer said:

> santosh wrote:
>> 
> ... snip ...
>> 
>> This is where a memory overwrite occurs:
>> 
>>   char *ptr;
>>   strcpy(ptr, "hello");
> 
> No it doesn't. It just blows up, because ptr was never initialized.

The behaviour is undefined. What santosh said is not unreasonable. In any 
case, you describe symptoms, whereas santosh is talking about causes.

-- 
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
0
Reply rjh (10789) 3/21/2008 6:54:07 AM

goodTweetieBird <goodTweetieBird@hotmail.com> writes:

>>
>> That's very true. Try taking some rather long input and storing it in
>> robots[0].name. That way, even the best of compilers can't guess how
>> much memory should be allocated for robots[0].name to allow for
>> robots[1].name and robots[2].name. After that, output it, and you can
>> usually find that robots[1].name and robots[2].name are overwritten.
<snip>
> Sounds like a source of subtle errors.

No, you have been misinformed.  Please read the other posts carefully.
If you don't understand, ask some more (and read the comp.lang.c FAQ
at http://c-faq.com/).

-- 
Ben.
0
Reply ben.usenet (6515) 3/21/2008 2:17:46 PM

On Thu, 20 Mar 2008 22:52:37 -0500, CBFalconer <cbfalconer@yahoo.com>
wrote in comp.lang.c:

> Eric Sosman wrote:
> > goodTweetieBird wrote:
> >
> >> In C I have seen the idiom
> >>
> >> char *name = "Tweety";
> >>
> >> and have been assured that it is legit. However I have doubts about
> >> the string assignments in the example below I found on the net. Are
> >> these string assignments valid?
> >>
> >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> #include <stdio.h>
> >>
> >> typedef struct robot ROBOT;
> >>
> >> struct robot {
> >>   char *name;
> >>   int energy;
> >> };
> >>
> >> int main() {
> >>   int i;
> >>
> >>   ROBOT robots[3];
> >>
> >>   robots[0].name = "Lunar Lee";
> >>   robots[0].energy = 50;
> >>   robots[1].name = "Planetary Pete";
> >>   robots[1].energy = 20;
> > 
> >      Yes, they are valid.  `robots[n].name' is a char*
> > (for n == 0,1,2), just as `name' is, so anything you
> > can do with `name' can also be done with `robots[n].name'.
> 
> You have set the pointer for name to point to a non-writable
> constant char. string.  So you can't diddle the names.  They are
> just there.  However, you can replace them.

Correction, you have set the pointer for name to point to a string
literal, which is an unnamed array of char (NOT "const char").  Any
attempt to modify a string literal because the C standard specifically
states it does, NOT because it is const qualified.

-- 
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
0
Reply jackklein (3932) 3/21/2008 4:11:23 PM

Jack Klein wrote:
> CBFalconer <cbfalconer@yahoo.com> wrote in comp.lang.c:
>> Eric Sosman wrote:
>>> goodTweetieBird wrote:
>>>
>>>> In C I have seen the idiom
>>>>
>>>> char *name = "Tweety";
>>>>
>>>> and have been assured that it is legit. However I have doubts about
>>>> the string assignments in the example below I found on the net. Are
>>>> these string assignments valid?
>>>>
>>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>> #include <stdio.h>
>>>>
>>>> typedef struct robot ROBOT;
>>>>
>>>> struct robot {
>>>>   char *name;
>>>>   int energy;
>>>> };
>>>>
>>>> int main() {
>>>>   int i;
>>>>
>>>>   ROBOT robots[3];
>>>>
>>>>   robots[0].name = "Lunar Lee";
>>>>   robots[0].energy = 50;
>>>>   robots[1].name = "Planetary Pete";
>>>>   robots[1].energy = 20;
>>>
>>>      Yes, they are valid.  `robots[n].name' is a char*
>>> (for n == 0,1,2), just as `name' is, so anything you
>>> can do with `name' can also be done with `robots[n].name'.
>>
>> You have set the pointer for name to point to a non-writable
>> constant char. string.  So you can't diddle the names.  They
>> are just there.  However, you can replace them.
> 
> Correction, you have set the pointer for name to point to a
> string literal, which is an unnamed array of char (NOT "const
> char").  Any attempt to modify a string literal because the C
> standard specifically states it does, NOT because it is const
> qualified.

I didn't say const.  I wrote 'constant'.  Do you deny that the
pointers are to constant strings?

-- 
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: <http://cbfalconer.home.att.net>
            Try the download section.



-- 
Posted via a free Usenet account from http://www.teranews.com

0
Reply cbfalconer (19183) 3/21/2008 4:53:23 PM

goodTweetieBird wrote:
> In C I have seen the idiom
> 
> char *name = "Tweety";
> 
> and have been assured that it is legit. 

It is legit. However, the practice of pointing to non-modifiable data 
with a non-const-qualified pointer in normally frowned upon, unless you 
have a good reason to do so. Without such a good reason it should be

   const char *name = "Tweety";

> However I have doubts about
> the string assignments in the example below I found on the net. Are
> these string assignments valid?
> ...
>   robots[0].name = "Lunar Lee";
> ...

Er... Well, they are not in any way different from your first example. 
Which brings the question of why you are even asking?

-- 
Best regards,
Andrey Tarasevich
0
Reply andreytarasevich (1531) 3/21/2008 6:14:02 PM

14 Replies
32 Views

(page loaded in 0.138 seconds)


Reply: