Array in struct

J

Jan Danielsson

Hello all,

I'm writing an XML parser, and I'd like to know how portable a
solution is.

When I pass an STag or EmptyElement tag to the application, I
(obviously) need to pass the attribute list somehow. I thought about
storing the list in something like this:

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[1];
}ATTRLIST, *PATTRLIST;

foo()
{
PATTRLIST pal = 0;
...blah...
if(nAttr > 0)
{
pal = malloc(sizeof(ATTRLIST)+(nAttr-1)*sizeof(ATTR))
...blah...
}
}

Now, what I'm worried about is portability. Is using an 1-sized array
like that a bad move? Does C guarantee that structure members are ordered?

Thankful for any advice.
 
N

Nick Keighley

Jan said:
I'm writing an XML parser, and I'd like to know how portable a
solution is.

When I pass an STag or EmptyElement tag to the application, I
(obviously) need to pass the attribute list somehow. I thought about
storing the list in something like this:

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[1];
}ATTRLIST, *PATTRLIST;

foo()
{
PATTRLIST pal = 0;
...blah...
if(nAttr > 0)
{
pal = malloc(sizeof(ATTRLIST)+(nAttr-1)*sizeof(ATTR))
...blah...
}
}

Now, what I'm worried about is portability. Is using an 1-sized array
like that a bad move?

from the FAQ:-
FAQ 2.6 "I came across some code that declared a structure with the
last member an array of one element, and then did some tricky
allocation to make it act like the array had several elements. Is this
legal or portable?"

It seems to be technically illegal but works on all known
implementations... You could pass two parameters a count and an array
of
attributes.

Does C guarantee that structure members are ordered?

yes.

<snip>


--
Nick Keighley

We recommend, rather, that users take advantage of the extensions of
GNU C and disregard the limitations of other compilers. Aside from
certain supercomputers and obsolete small machines, there is less
and less reason ever to use any other C compiler other than for
bootstrapping GNU CC.
(Using and Porting GNU CC)
 
K

Kenneth Brody

Jan Danielsson wrote:
[...]
typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[1];
}ATTRLIST, *PATTRLIST;

foo()
{
PATTRLIST pal = 0;
...blah...
if(nAttr > 0)
{
pal = malloc(sizeof(ATTRLIST)+(nAttr-1)*sizeof(ATTR))
...blah...
}
}

Now, what I'm worried about is portability. Is using an 1-sized array
like that a bad move? Does C guarantee that structure members are ordered?
[...]

As someone else pointed out, the FAQ says it's "technically illegal",
but it "works on all known implementations".

You could get around this, if you want to not worry about it, by using
something like:

typedef struct _ATTRLIST
{
int numAttr;
ATTR *attr;
}
ATTRLIST, *PATTRLIST;

...
pal = malloc(sizeof(ATTRLIST));
if ( pal != NULL )
{
pal->attr = malloc(nAttr*sizeof(*pal->attr));
...

You also have to remember to free pal->attr as well as pal.

On the other hand, I do have to admit that I use the 1-element array
version in numerous places, and have had no problems on all the
various platforms I've ported to.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
T

Tobias Blomkvist

Jan Danielsson sade:
Hello all,

I'm writing an XML parser, and I'd like to know how portable a
solution is.

When I pass an STag or EmptyElement tag to the application, I
(obviously) need to pass the attribute list somehow. I thought about
storing the list in something like this:

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[1];
}ATTRLIST, *PATTRLIST;

foo()
{
PATTRLIST pal = 0;
...blah...
if(nAttr > 0)
{
pal = malloc(sizeof(ATTRLIST)+(nAttr-1)*sizeof(ATTR))
...blah...
}
}

Now, what I'm worried about is portability. Is using an 1-sized array
like that a bad move? Does C guarantee that structure members are ordered?

Thankful for any advice.

The c99 standard provides a feature called a flexible array member which
is a portable struct hack.

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[];
} ATTRLIST, *PATTRLIST;

PATTRLIST p = malloc(sizeof(ATTRLIST) + sizeof(ATTR) * 10);

Tobias
 
E

Eric Laberge

Tobias said:
The c99 standard provides a feature called a flexible array member which
is a portable struct hack.

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[];
} ATTRLIST, *PATTRLIST;

PATTRLIST p = malloc(sizeof(ATTRLIST) + sizeof(ATTR) * 10);

Tobias

Nice to know it is actually legal and portable! I've been using this a lot
and never took the time to check if it was an OK construct or if it gave me
the correct size for malloc.

Where in the standard is this defined? I've decided to actually read the
standard but am still in the beginnings of the document...
 
T

Tobias Blomkvist

Eric Laberge sade:
Tobias Blomkvist wrote:

The c99 standard provides a feature called a flexible array member which
is a portable struct hack.

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[];
} ATTRLIST, *PATTRLIST;

PATTRLIST p = malloc(sizeof(ATTRLIST) + sizeof(ATTR) * 10);

Tobias


Nice to know it is actually legal and portable! I've been using this a lot
and never took the time to check if it was an OK construct or if it gave me
the correct size for malloc.

Where in the standard is this defined? I've decided to actually read the
standard but am still in the beginnings of the document...

Section 6.7.2.1

Tobias
 
K

Keith Thompson

Eric Laberge said:
Tobias said:
The c99 standard provides a feature called a flexible array member which
is a portable struct hack.

typedef struct _ATTRLIST
{
int numAttr;
ATTR attr[];
} ATTRLIST, *PATTRLIST;

PATTRLIST p = malloc(sizeof(ATTRLIST) + sizeof(ATTR) * 10);

Tobias

Nice to know it is actually legal and portable! I've been using this a lot
and never took the time to check if it was an OK construct or if it gave me
the correct size for malloc.

Where in the standard is this defined? I've decided to actually read the
standard but am still in the beginnings of the document...

For features defined in C99 but not in C90, "legal" does not
necessarily imply "portable". The C99 standard is not univerally
implemented.
 
M

Michael Wojcik

I'm writing an XML parser, and I'd like to know how portable a
solution is.

When I pass an STag or EmptyElement tag to the application, I
(obviously) need to pass the attribute list somehow. I thought about
storing the list in something like this:

typedef struct _ATTRLIST

Others have already discussed the "struct hack", but note also that
identifiers beginning with an underscore followed by an uppercase
letter are always reserved to the implementation. You cannot
portably use the struct tag "_ATTRLIST" for your own structure.
Similarly, any identifier that begins with an underscore is reserved
at file scope. Best bet: don't begin your identifiers with under-
scores. C90 7.1.3.

(Personally, I don't see why you use both a struct tag and a typedef,
since the struct doesn't contain a pointer to the same struct type.
My preference is to avoid typedef in nearly all situations, and
particularly to not disguise a pointer type using typedef, but those
are questions of style. Also, I avoid identifiers in block capitals;
some like to reserve those for macro names, but I use mixed case for
all identifiers as I've found that reduces the likelihood of name
collisions in the environments where my code is typically compiled.
That too is a style issue, of course.)
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top