Array of structs with strings

Discussion in 'C Programming' started by goodTweetieBird, Mar 21, 2008.

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

    ....
     
    goodTweetieBird, Mar 21, 2008
    #1
    1. Advertising

  2. goodTweetieBird

    Eric Sosman Guest

    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
    lid
     
    Eric Sosman, Mar 21, 2008
    #2
    1. Advertising


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


    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
     
    goodTweetieBird, Mar 21, 2008
    #3
  4. goodTweetieBird

    rpgfan3233 Guest

    On Mar 20, 9:51 pm, 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'.

    >
    > > --
    > > Eric Sosman
    > >

    >
    > 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!
     
    rpgfan3233, Mar 21, 2008
    #4
  5. >
    > 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
     
    goodTweetieBird, Mar 21, 2008
    #5
  6. goodTweetieBird

    Eric Sosman Guest

    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
    lid
     
    Eric Sosman, Mar 21, 2008
    #6
  7. goodTweetieBird

    santosh Guest

    rpgfan3233 wrote:

    > On Mar 20, 9:51 pm, 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'.

    >>
    >> > --
    >> > Eric Sosman
    >> >

    >>
    >> 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");
     
    santosh, Mar 21, 2008
    #7
  8. goodTweetieBird

    CBFalconer Guest

    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
     
    CBFalconer, Mar 21, 2008
    #8
  9. goodTweetieBird

    CBFalconer Guest

    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
     
    CBFalconer, Mar 21, 2008
    #9
  10. goodTweetieBird <> 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) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 21, 2008
    #10
  11. 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
     
    Richard Heathfield, Mar 21, 2008
    #11
  12. goodTweetieBird <> 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.
     
    Ben Bacarisse, Mar 21, 2008
    #12
  13. goodTweetieBird

    Jack Klein Guest

    On Thu, 20 Mar 2008 22:52:37 -0500, CBFalconer <>
    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
     
    Jack Klein, Mar 21, 2008
    #13
  14. goodTweetieBird

    CBFalconer Guest

    Jack Klein wrote:
    > CBFalconer <> 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
     
    CBFalconer, Mar 21, 2008
    #14
  15. 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
     
    Andrey Tarasevich, Mar 21, 2008
    #15
    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. Patricia  Van Hise

    structs with fields that are structs

    Patricia Van Hise, Apr 5, 2004, in forum: C Programming
    Replies:
    5
    Views:
    670
    Al Bowers
    Apr 5, 2004
  2. Chris Hauxwell

    const structs in other structs

    Chris Hauxwell, Apr 23, 2004, in forum: C Programming
    Replies:
    6
    Views:
    590
    Chris Hauxwell
    Apr 27, 2004
  3. Paminu
    Replies:
    5
    Views:
    661
    Eric Sosman
    Oct 11, 2005
  4. Daniel Rudy
    Replies:
    15
    Views:
    1,452
    Keith Thompson
    Apr 10, 2006
  5. Tuan  Bui
    Replies:
    14
    Views:
    532
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page