![]() |
|
|
|||||||
![]() |
C Programming - structure containing incomplete array type |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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.] Eric Smith |
|
|
|
|
#2 |
|
Posts: n/a
|
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. Jeremy Yallop |
|
|
|
#3 |
|
Posts: n/a
|
Jeremy Yallop <> 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 Eric Smith |
|
|
|
#4 |
|
Posts: n/a
|
Eric Smith wrote:
> Jeremy Yallop <> 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 () () Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net> USE worldnet address! CBFalconer |
|
|
|
#5 |
|
Posts: n/a
|
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. Martin Ambuhl |
|
|
|
#6 |
|
Posts: n/a
|
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. Jeremy Yallop |
|
|
|
#7 |
|
Posts: n/a
|
In message <>
CBFalconer <> 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/ Kevin Bracey |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Error: expected constructor, destructor or type conversion before '(' token | suse | Software | 0 | 03-09-2009 03:25 AM |
| Eclipse - Axis2 - Java Webservices Error | amanjsingh | Software | 1 | 10-09-2007 09:03 AM |
| Need help on Modelsim VHDL syntax? ASAP:) | kaji | General Help Related Topics | 0 | 03-14-2007 10:43 PM |
| Need help on a Modelsim VHDL Syntax? ASAP:) | kaji | Software | 0 | 03-14-2007 10:43 PM |
| Need Help on a Modelsim VHDL Syntax....ASAP:) | kaji | Hardware | 0 | 03-14-2007 10:41 PM |