Declaring structs with anonymous arrays

Discussion in 'C Programming' started by andreyvul, Sep 30, 2008.

  1. andreyvul

    andreyvul Guest

    I'm trying to do the following:

    typedef struct {
    char *bar;
    char **baz;
    } foo;

    const foo fop[] = {
    { "foo", { "bar", "baz", "bax" } },
    { "goo", { "car", "cdr", "cfr" } }
    };

    Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    before the "bar" and the '}' following the "bar",
    and the same situation for "car" and "cfr".
    Any suggestions?
    andreyvul, Sep 30, 2008
    #1
    1. Advertising

  2. andreyvul

    andreyvul Guest

    Eric Sosman wrote:
    > andreyvul wrote:
    > > I'm trying to do the following:
    > >
    > > typedef struct {
    > > char *bar;
    > > char **baz;
    > > } foo;
    > >
    > > const foo fop[] = {
    > > { "foo", { "bar", "baz", "bax" } },
    > > { "goo", { "car", "cdr", "cfr" } }
    > > };
    > >
    > > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > > before the "bar" and the '}' following the "bar",
    > > and the same situation for "car" and "cfr".
    > > Any suggestions?

    >
    > If you're willing to waive anonymity:
    >
    > static char *fop0[] = { "bar", "baz", "bax", };
    > static char *fop1[] = { "car", "cdr", "cfr", };
    > const foo fop[] = {
    > { "foo", fop0 },
    > { "goo", fop1 },
    > };
    >
    > Add qualifiers as desired.
    >

    Is there a way for anonymity to remain, i.e. similar to my example,
    without violating ANSI C 90/99? Unfortunately VC isn't as standards-
    conformant as gcc, so if hacks are needed, give an example
    (preprocessor only, please) such as how to use the preprocessor as a
    compiler for ENTRY{str, array} entries.
    andreyvul, Sep 30, 2008
    #2
    1. Advertising

  3. andreyvul

    Guest

    andreyvul wrote:
    > I'm trying to do the following:
    >
    > typedef struct {
    > char *bar;
    > char **baz;
    > } foo;
    >
    > const foo fop[] = {
    > { "foo", { "bar", "baz", "bax" } },
    > { "goo", { "car", "cdr", "cfr" } }
    > };
    >
    > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > before the "bar" and the '}' following the "bar",
    > and the same situation for "car" and "cfr".
    > Any suggestions?


    Look at the thread from 2008-09-22 in this newsgroup titled
    "Initialization Problem": <http://groups.google.com/group/comp.lang.c/
    browse_frm/thread/4aef0fbeb2f5693c/13f2da24e390e955?
    lnk=st&q=#13f2da24e390e955>

    If you can restrict the portability of your code to compilers which
    support the C99 feature of compound literals, then you can write:

    const foo fop = {
    { "foo", (char *[]){"bar", "baz", "bax"}},
    ....

    The key problem is that you have to allocate space for foo.baz,
    foo.baz[j], and foo.baz[j][k]. Your code doesn't allocate any
    memory for foo.baz[j]. Compound literals allocate space with static
    storage duration for the arrays that they point to, just like string
    literals do.

    Notice that this is much simpler than the corresponding code in the
    "Initialization Problem" thread, because you're using char where
    Thorsten Schilling was using int. As a result, you can use string
    literals for much of the work. His version had to use compound
    literals everywhere.
    , Sep 30, 2008
    #3
  4. andreyvul

    andreyvul Guest

    wrote:
    > andreyvul wrote:
    > > I'm trying to do the following:
    > >
    > > typedef struct {
    > > char *bar;
    > > char **baz;
    > > } foo;
    > >
    > > const foo fop[] = {
    > > { "foo", { "bar", "baz", "bax" } },
    > > { "goo", { "car", "cdr", "cfr" } }
    > > };
    > >
    > > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > > before the "bar" and the '}' following the "bar",
    > > and the same situation for "car" and "cfr".
    > > Any suggestions?

    >
    > Look at the thread from 2008-09-22 in this newsgroup titled
    > "Initialization Problem": <http://groups.google.com/group/comp.lang.c/
    > browse_frm/thread/4aef0fbeb2f5693c/13f2da24e390e955?
    > lnk=st&q=#13f2da24e390e955>
    >
    > If you can restrict the portability of your code to compilers which
    > support the C99 feature of compound literals, then you can write:
    >
    > const foo fop = {
    > { "foo", (char *[]){"bar", "baz", "bax"}},
    > ...
    >
    > The key problem is that you have to allocate space for foo.baz,
    > foo.baz[j], and foo.baz[j][k]. Your code doesn't allocate any
    > memory for foo.baz[j]. Compound literals allocate space with static
    > storage duration for the arrays that they point to, just like string
    > literals do.

    Well then, I'm switching to MinGW from VC then.
    andreyvul, Sep 30, 2008
    #4
  5. andreyvul wrote:
    > I'm trying to do the following:



    typedef struct
    {
    char *bar;
    char *baz[3]; /* was char **baz */
    } foo;

    const foo fop[] = {
    {"foo", {"bar", "baz", "bax"}},
    {"goo", {"car", "cdr", "cfr"}}
    };



    > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > before the "bar" and the '}' following the "bar",
    > and the same situation for "car" and "cfr".
    > Any suggestions?


    The double indirection '**baz' is the problem. If you want that form,
    you will need to allocate space for the pointer array, which will make
    the 'const' suspect and filling the structure by an initializer problematic.
    Martin Ambuhl, Sep 30, 2008
    #5
  6. andreyvul

    Flash Gordon Guest

    Eric Sosman wrote, On 30/09/08 18:43:
    > andreyvul wrote:


    <snip>

    >> Is there a way for anonymity to remain, i.e. similar to my example,
    >> without violating ANSI C 90/99?


    <snip>

    >> Unfortunately VC isn't as standards-
    >> conformant as gcc,

    >
    > Yikes!


    No need for the "Yikes!". MSVC actually conforms very well to C90 when
    properly prompted (probably about as well as gcc when gcc is properly
    prompted).

    <snip>

    > James Kuyper suggests using compound literals, which seems a
    > plausible approach. But they're a C99 feature, and from all I've
    > read Microsoft have not been prompt to introduce C99 support (but
    > my information may be wrong; check for yourself).


    I believe you are correct and MS have done negligible work towards C99.
    --
    Flash Gordon
    If spamming me sent it to
    If emailing me use my reply-to address
    See the comp.lang.c Wiki hosted by me at http://clc-wiki.net/
    Flash Gordon, Sep 30, 2008
    #6
  7. andreyvul

    Guest

    On Sep 30, 7:45 pm, andreyvul <> wrote:
    > I'm trying to do the following:
    >
    > typedef struct {
    > char *bar;
    > char **baz;
    >
    > } foo;
    >
    > const foo fop[] = {
    > { "foo", { "bar", "baz", "bax" } },
    > { "goo", { "car", "cdr", "cfr" } }
    >
    > };
    >
    > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > before the "bar" and the '}' following the "bar",
    > and the same situation for "car" and "cfr".
    > Any suggestions?




    C99 solution:

    const foo fop[] = {
    { "foo", (char *[]){ "bar", "baz", "bax"} },
    { "goo", (char *[]){ "car", "cdr", "cfr" } }
    };

    However, you can't modify the strings baz points to, because they're
    string literals.
    To fix this...

    #define NOTLITERAL(x) (char []){x}

    const foo fop[] = {
    { "foo", (char *[]){ NOTLITERAL("bar"), NOTLITERAL("baz"),
    NOTLITERAL("bax") } },
    { /* ... */
    };
    , Sep 30, 2008
    #7
  8. andreyvul

    andreyvul Guest

    wrote:
    > On Sep 30, 7:45 pm, andreyvul <> wrote:
    > > I'm trying to do the following:
    > >
    > > typedef struct {
    > > char *bar;
    > > char **baz;
    > >
    > > } foo;
    > >
    > > const foo fop[] = {
    > > { "foo", { "bar", "baz", "bax" } },
    > > { "goo", { "car", "cdr", "cfr" } }
    > >
    > > };
    > >
    > > Now, MSVC 8 (VC++ 2005) states compilation failure due to the '{'
    > > before the "bar" and the '}' following the "bar",
    > > and the same situation for "car" and "cfr".
    > > Any suggestions?

    >
    >
    >
    > C99 solution:
    >
    > const foo fop[] = {
    > { "foo", (char *[]){ "bar", "baz", "bax"} },
    > { "goo", (char *[]){ "car", "cdr", "cfr" } }
    > };

    Which can be converted into a macro: #define stringarray(...) (const
    char *[]){ __VA_ARGS__, NULL}
    Then replace (char *[]){ "bar", "baz", "bax", NULL} with
    stringarray("bar", "baz", "bax")
    Note: I reuse the NULL functionality of char* strings in char**
    arrays.
    >
    > However, you can't modify the strings baz points to, because they're
    > string literals.

    Not necessary. My code requires use of const char ** and const char*.
    The "de-constification" is unneeded.
    andreyvul, Sep 30, 2008
    #8
    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:
    619
    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:
    545
    Chris Hauxwell
    Apr 27, 2004
  3. Paminu
    Replies:
    5
    Views:
    630
    Eric Sosman
    Oct 11, 2005
  4. Daniel Rudy
    Replies:
    15
    Views:
    1,368
    Keith Thompson
    Apr 10, 2006
  5. Markus Svilans

    Declaring structs vs. classes

    Markus Svilans, May 15, 2006, in forum: C++
    Replies:
    7
    Views:
    363
    Markus Svilans
    May 16, 2006
Loading...

Share This Page