473,383 Members | 1,876 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

structure containing incomplete array type

Is a structure containing an incomplete array as its last element (per
paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an
incomplete type? That appears to be indicated by paragraph 22 of
section 6.2.5. If so, that seems to make it difficult to allocate such
structures, because sizeof() is not allowed on incomplete types
(paragraph 1 of section 6.5.3.4).

For instance, I've routinely done things like this:

struct foo { int a; char b; double c []; };

struct foo *alloc_foo (int s)
{
return (calloc (1, sizeof (struct foo) + sizeof (double) * s));
}

But section 6.2.5 seems to make this invalid.

Is this the correct interpretation? If so, is there some other
valid way to implement alloc_foo()?

On the other hand, paragraph 3 of section 6.7.2.3 states that the
declaration of a structure type is complete after the closing brace,
without any caveat about incomplete elements of the structure.

In writing this, I've started to wonder whether it's really specified
that the size of an array of a particular element type is equal to the
product of the array size and the size of the element type. I can't
find anything suggesting that this is required. If it's not, is there
some way given an integer expression to get the size of an array of that
many elements of a particular type? Something like sizeof(double [s])?

I used to think that using Ada's constrained record types was a hassle,
but now I'm not convinced that the C99 incomplete array in a structure
feature is any better.

Thanks,
Eric Smith

[I'll watch for replies to the newsgroup, but if you want to reply by
email, please remove the obvious spam-proofing from my email address.]
Nov 14 '05 #1
6 1877
Eric Smith wrote:
Is a structure containing an incomplete array as its last element (per
paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an
incomplete type? That appears to be indicated by paragraph 22 of
section 6.2.5. If so, that seems to make it difficult to allocate such
structures, because sizeof() is not allowed on incomplete types
(paragraph 1 of section 6.5.3.4).
I think that a struct with a flexible array member has complete type,
although the array has incomplete type. 6.7.2.1#16 covers the
behaviour of sizeof on such structs:

[T]he size of the structure shall be equal to the offset of the
last element of an otherwise identical structure that replaces the
flexible array member with an array of unspecified length.
In writing this, I've started to wonder whether it's really specified
that the size of an array of a particular element type is equal to the
product of the array size and the size of the element type. I can't
find anything suggesting that this is required.
This follows directly from the definition of an array:

An array type describes a contiguously allocated nonempty set of
objects with a particular member object type, called the element
type.

Since the elements are "contiguously allocated", the size of the array
is simply the sum of the sizes of the elements. This is different
from structs, whose members are merely "sequentially allocated". I
think it follows from the way pointer arithmetic is defined, as well,
but I haven't checked.
If it's not, is there some way given an integer expression to get
the size of an array of that many elements of a particular type?
Something like sizeof(double [s])?


`sizeof(double[s])' is valid in C99 (and in C89 if `s' is an integer
constant expression). `double[s]' is a type-name.

Jeremy.
Nov 14 '05 #2
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
I think that a struct with a flexible array member has complete type,
although the array has incomplete type. 6.7.2.1#16 covers the
behaviour of sizeof on such structs:

[T]he size of the structure shall be equal to the offset of the
last element of an otherwise identical structure that replaces the
flexible array member with an array of unspecified length.
That's what I needed! Somehow I'd overlooked that paragraph.
This follows directly from the definition of an array:

An array type describes a contiguously allocated nonempty set of
objects with a particular member object type, called the element
type.


Ah! So the compiler can't add padding bytes for alignment. I had the
mistaken impression that it was permissible for the compiler to add
padding. For instance, on an architecture with four-byte integers
required to be four-byte aligned, I thought some padding might be used
in a case like this:

struct foo_t { int a; char b; }; /* sizeof(struct foo_t) == 5 */

struct foo_t bar [12];

I'd previously expected that to result in the size of the array being
96 bytes, but based on the array definition you've quoted (6.2.5#20),
apparently it would only be 60 bytes. I suppose the compiler would be
required to generate appropriate code for the misaligned integers, or
to make sizeof(struct foo_t) be a multiple of four.

Thanks!
Eric
Nov 14 '05 #3
Eric Smith wrote:
Jeremy Yallop <je****@jdyallop.freeserve.co.uk> writes:
I think that a struct with a flexible array member has complete
type, although the array has incomplete type. 6.7.2.1#16 covers
the behaviour of sizeof on such structs:

[T]he size of the structure shall be equal to the offset of the
last element of an otherwise identical structure that replaces
the flexible array member with an array of unspecified length.


That's what I needed! Somehow I'd overlooked that paragraph.
This follows directly from the definition of an array:

An array type describes a contiguously allocated nonempty set
of objects with a particular member object type, called the
element type.


Ah! So the compiler can't add padding bytes for alignment. I
had the mistaken impression that it was permissible for the
compiler to add padding. For instance, on an architecture with
four-byte integers required to be four-byte aligned, I thought
some padding might be used in a case like this:

struct foo_t { int a; char b; }; /* sizeof(struct foo_t) == 5 */

struct foo_t bar [12];

I'd previously expected that to result in the size of the array
being 96 bytes, but based on the array definition you've quoted
(6.2.5#20), apparently it would only be 60 bytes. I suppose the
compiler would be required to generate appropriate code for the
misaligned integers, or to make sizeof(struct foo_t) be a
multiple of four.


You were right the first time. It doesn't pad between array
elements, but the elements themselves are padded so that they
don't need it. That 5 above is probably 8.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #4
Eric Smith wrote:
Is a structure containing an incomplete array as its last element (per
paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an
incomplete type? That appears to be indicated by paragraph 22 of
section 6.2.5.
"Appears to indicated"? If explicit words only "appear to indicate,"
something is terribly wrong:
[#23] ... A structure type
containing a flexible array member is an incomplete type
that cannot be completed.

If so, that seems to make it difficult to allocate such
structures, because sizeof() is not allowed on incomplete types
(paragraph 1 of section 6.5.3.4).
Did you not read in that same section 6.7.2.1
[#15] As a special case, the last element of a structure
with more than one named member may have an incomplete array
type. This is called a flexible array member, and the size
of the structure shall be equal to the offset of the last
element of an otherwise identical structure that replaces
the flexible array member with an array of unspecified
length.97) When an lvalue whose type is a structure with a
flexible array member is used to access an object, it
behaves as if that member were replaced with the longest
array, with the same element type, that would not make the
structure larger than the object being accessed; the offset
of the array shall remain that of the flexible array member,
even if this would differ from that of the replacement
array. If this array would have no elements, then it
behaves as if it had one element, but the behavior is
undefined if any attempt is made to access that element or
to generate a pointer one past it.
For instance, I've routinely done things like this:

struct foo { int a; char b; double c []; };

struct foo *alloc_foo (int s)
{
return (calloc (1, sizeof (struct foo) + sizeof (double) * s));
}

But section 6.2.5 seems to make this invalid.
Did you not read in that same section 6.7.2.1
[#16] EXAMPLE Assuming that all array members are aligned
the same, after the declarations:

struct s { int n; double d[]; };
struct ss { int n; double d[1]; };

the three expressions:

sizeof (struct s)
offsetof(struct s, d)
offsetof(struct ss, d)

have the same value. The structure struct s has a flexible
array member d.

[#17] If sizeof (double) is 8, then after the following code
is executed:

struct s *s1;
struct s *s2;
s1 = malloc(sizeof (struct s) + 64);
s2 = malloc(sizeof (struct s) + 46);

and assuming that the calls to malloc succeed, the objects
pointed to by s1 and s2 behave as if the identifiers had
been declared as:

struct { int n; double d[8]; } *s1;
struct { int n; double d[5]; } *s2;

[#18] Following the further successful assignments:

s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);

they then behave as if the declarations were:

struct { int n; double d[1]; } *s1, *s2;

and:

double *dp;
dp = &(s1->d[0]); // Permitted
*dp = 42; // Permitted
dp = &(s2->d[0]); // Permitted
*dp = 42; // Undefined behavior

Is this the correct interpretation?


For someone who quotes section numbers of the standard, you seem to have
done precious little in the way of reading it.
Nov 14 '05 #5
Martin Ambuhl wrote:
Eric Smith wrote:
Is a structure containing an incomplete array as its last element (per
paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an
incomplete type? That appears to be indicated by paragraph 22 of
section 6.2.5.
"Appears to indicated"? If explicit words only "appear to indicate,"
something is terribly wrong:
[#23] ... A structure type
containing a flexible array member is an incomplete type
that cannot be completed.


Those words don't appear in the standard, although they do in draft
versions. I believe them to be false as a statement about C99.
If so, that seems to make it difficult to allocate such
structures, because sizeof() is not allowed on incomplete types
(paragraph 1 of section 6.5.3.4).


Did you not read in that same section 6.7.2.1


The words you quote have also been changed in the standard and it
would be unwise to rely upon them.
Did you not read in that same section 6.7.2.1
[#16] EXAMPLE
The text of these examples has been changed between the final public
draft and the actual standard.
For someone who quotes section numbers of the standard, you seem to have
done precious little in the way of reading it.


"n869" is not the standard.

Jeremy.
Nov 14 '05 #6
In message <40***************@yahoo.com>
CBFalconer <cb********@yahoo.com> wrote:
Eric Smith wrote:
Ah! So the compiler can't add padding bytes for alignment. I
had the mistaken impression that it was permissible for the
compiler to add padding. For instance, on an architecture with
four-byte integers required to be four-byte aligned, I thought
some padding might be used in a case like this:

struct foo_t { int a; char b; }; /* sizeof(struct foo_t) == 5 */

struct foo_t bar [12];

I'd previously expected that to result in the size of the array
being 96 bytes, but based on the array definition you've quoted
(6.2.5#20), apparently it would only be 60 bytes. I suppose the
compiler would be required to generate appropriate code for the
misaligned integers, or to make sizeof(struct foo_t) be a
multiple of four.


You were right the first time. It doesn't pad between array
elements, but the elements themselves are padded so that they
don't need it. That 5 above is probably 8.


Indeed, but as we were originally talking about flexible array members, it's
worth noting one possible implementation quirk:

struct foo_t { int a; char b; }; /* sizeof(struct foo_t) == 8 */
struct jim_t { int a; char b; char c[1]; }; /* sizeof(struct jim_t) == 8 */
struct bar_t { int a; char b; char c[]; } /* sizeof(struct bar_t) == 5 */

That's quite possible, and a logical way to implement flexible array members.
(The alternative would be to add 3 bytes of padding between b and c in
bar_t). Structures with flexible array members cannot be elements of arrays,
so trailing padding is not needed to ensure alignment of the int. Our
implementation works in this way.

FWIW, this is one of gcc's non-conformances to C99 - its sizeof(struct bar_t)
== 8, but offsetof(bar_t, c) == 5.

--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW: http://www.tematic.com/
Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Tien Pham via .NET 247 | last post by:
(Type your message here) -------------------------------- From: Tien Pham I am having problems with intptr. Or maybe i am not using it properly. What it is that i am having problem with is...
5
by: Paul F. Dietz | last post by:
Is the following legal C? struct foo; struct foo (*p); /* Pointer to array of 10 foo structures */ struct foo { int bar; int baz; }; main() { printf("%d\n", sizeof(*p)); } Paul Dietz...
6
by: Eric Smith | last post by:
Is a structure containing an incomplete array as its last element (per paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an incomplete type? That appears to be indicated by paragraph...
15
by: damian birchler | last post by:
Hi I'm wondering of what type a structure is. Of course, it is a _structure_, but an array isn't an _array_ either. So of what type is a structure? I'd say a pointer, am I right?
2
by: vikas | last post by:
I have following structure in c++. typedef struct MMF_result_struct { int action; char text; int cols,rows; int month,day,year; } MMF_result; Now this structure is shared between C++ and C#...
3
by: Steve | last post by:
Hello, I created a public Structure in a Standard Module and also an array of Structures. Then I load data into the array of structures in a public sub that I call on the Form load event. ...
10
by: David Fort | last post by:
Hi, I'm upgrading a VB6 app to VB.net and I'm having a problem with a call to a function provided in a DLL. The function takes the address of a structure which it will fill in with values. I...
3
by: bill | last post by:
All, I have the following: ...... unsafe public struct Example { public double we;
10
by: arcadio | last post by:
Hi everyone, I'm currently struggling to compile a large piece of legacy code. GCC 3.3 compiles it without complaining, but GCC 4.2.3 (the default in Debian) refuses it and signals "several...
5
by: =?Utf-8?B?QXlrdXQgRXJnaW4=?= | last post by:
Hi Willy, Thank you very much for your work. C++ code doesnot make any serialization. So at runtime C# code gives an serialization error at "msg_file_s sa = (msg_file_s) bf.Deserialize(ms);"...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.