Declaring structs with anonymous arrays

A

andreyvul

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?
 
A

andreyvul

Eric said:
andreyvul said:
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.
 
J

jameskuyper

andreyvul said:
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.
 
A

andreyvul

andreyvul said:
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.
 
M

Martin Ambuhl

andreyvul said:
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.
 
F

Flash Gordon

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



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

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

vippstar

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") } },
{ /* ... */
};
 
A

andreyvul

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top