Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Why is initializing a FAM invalid?

Reply
Thread Tools

Why is initializing a FAM invalid?

 
 
James Kuyper
Guest
Posts: n/a
 
      11-10-2010
On 11/10/2010 02:09 AM, Michael Foukarakis wrote:
....
> My quibble is why
>
> struct s { int x; char d[]; } e = { 0, "foo" };
>
> produces the same error, as there is at least one way to resolve it
> without conflicting with the wording of the standard.


What is that "one way to resolve it"?

The standard can be read as requiring that an array of char be allocated
for "foo" itself, and that e.d be initialized by copying from that
array. However, there's no way for strictly conforming code to get the
address of that array, and therefore no way for such code to make any
use of that fact.

Aside from that issue, that declaration is semantically equivalent to

struct s { int x; char d[]; } e = { 0, {'f', 'o', 'o', '\0'} };

which still provides initializers for four char objects (e.d[0] through
e.d[3]) for which no space need have been allocated. That's still a
constraint violation (6.7.8p1).
 
Reply With Quote
 
 
 
 
Michael Foukarakis
Guest
Posts: n/a
 
      11-12-2010
On Nov 10, 1:06*pm, James Kuyper <jameskuy...@verizon.net> wrote:
> On 11/10/2010 02:09 AM, Michael Foukarakis wrote:
> ...
>
> > My quibble is why

>
> > * * * * *struct s { int x; char d[]; } e = { 0, "foo" };

>
> > produces the same error, as there is at least one way to resolve it
> > without conflicting with the wording of the standard.

>
> What is that "one way to resolve it"?


Assuming "foo" is a string constant and initializing the FAM
accordingly. However, as you also said, gcc is just being consistent,
which is, after some thought, much better than distinguishing between
the two cases.

2c
 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      11-12-2010
On 11/12/2010 04:18 AM, Michael Foukarakis wrote:
> On Nov 10, 1:06�pm, James Kuyper<jameskuy...@verizon.net> wrote:
>> On 11/10/2010 02:09 AM, Michael Foukarakis wrote:
>> ...
>>
>>> My quibble is why

>>
>>> � � � � �struct s { int x; char d[]; } e = { 0, "foo" };

>>
>>> produces the same error, as there is at least one way to resolve it
>>> without conflicting with the wording of the standard.

>>
>> What is that "one way to resolve it"?

>
> Assuming "foo" is a string constant and initializing the FAM
> accordingly. However, as you also said, gcc is just being consistent,
> which is, after some thought, much better than distinguishing between
> the two cases.


I don't see that as a solution to the basic problem, which is that there
is no guarantee that e is big enough to contain e.d[3], which would
otherwise be initialized by the '\0' terminating that string. It's not
even guaranteed to be big enough to contain e.d[0], which would be
initialized with the 'f'. If offsetof(struct s,d) == sizeof(struct s),
as is perfectly permissible, then the definition of 'e' provides more 4
more initializers than there are objects available to be initialized. So
it still violates the constraint in 6.7.8p1.
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      11-12-2010
Wojtek Lerch wrote:

> On 08/11/2010 6:08 PM, Johannes Schaub (litb) wrote:
>> Wojtek Lerch wrote:
>>> "Marcin Grzegorczyk"<> wrote in message
>>> news:ib9jl4$mec$...
>>>> Wojtek Lerch wrote:
>>>>> "Wojtek Lerch"<> wrote in message
>>>>> news:...
>>>>>> "Marcin Grzegorczyk"<> wrote in message
>>>>>> news:ib4h3f$g0j$...
>>>>>>> [...] GCC, for example, allows FAM
>>>>>>> initialization as an extension. [...]
>>>>>>
>>>>>> What does sizeof return when applied to the name of such object?
>>>>>
>>>>> To answer my own question, sizeof does not include the FAM. The
>>>>> analogy with arrays of unknown size is bogus.
>>>>
>>>> The analogy was supposed to apply to how a compiler determines the size
>>>> of an object, and my point was that there are situations where the size
>>>> is known only after the initialization has been parsed.
>>>
>>> But even that analogy is not very good: in the case of normal arrays,
>>> the initializer determines the *type* of the object, and then the size
>>> follows
>>> from the type in the usual way. In the case of a structure with a FAM,
>>> the type of the object is the struct, and the size of that type does not
>>> include
>>> the array (or at least not necessarily all of it). Since the size of
>>> the object, as reported by sizeof, doesn't include the array either, one
>>> could argue that the array doesn't really belong to the declared object,
>>> but to a
>>> larger unnamed object that contains both the struct and the array.
>>> (That's, BTW, more or less how this extension is explained by GCC
>>> documentation.)

>>
>> I think the C99 Standard [...]

>
> You do realize that the discussion was not about a standard feature, but
> a GCC extension, right?
>


I wanted to show that according to the C99 Standard (in my interpretation),
it doesn't have to be an extension. I'm sorry if i slightly missed the
intention of this thread.

>> [...] makes no difference between non-subobjects and
>> subobjects. It just says
>>
>> "Each brace-enclosed initializer list has an associated current object.
>> When no designations are present, subobjects of the current object are
>> initialized in order according to the type of the current object [...]"

>
> Um... It says "subobjects" right there, and doesn't mention
> non-subobjects. Is that not a difference?
>


It says "subobjects ... are initialized ..." here, and in the following text
it says "If an array of unknown size is initialized...". These two
paragraphs fit perfectly together, I think.

>> "If an array of unknown size is initialized, its size is determined by
>> the largest indexed element with an explicit initializer. At the end of
>> its initializer list, the array no longer has incomplete type."
>>
>> I think this states that the FAM's size is correctly determined by that
>> procedure.

>
> Does it? What is the type of the FAM before and after the initializer?
>


I'm not really sure how I should interpret this wording. The meaning that is
compatible with my reading is: The effective type of the object is an array
type with that many initializers.

That does not, in my reading, necessarily mean that any expression refering
to it (like, a member access) actually has that type too. The aliasing rules
allow an object whose effective type is "T[N]" be accessed by an lvalue of
type "T[]".

>>>> This does not
>>>> have to do anything with sizeof.
>>>
>>> Other than the fact that sizeof is supposed to report the size of the
>>> object.

>>
>> It can't report the size of objects, because that is only known at
>> runtime. It therefor only reports "from the type of the operand.".

>
> Right. But does that mean that an object declared using the GCC
> extension is bigger than its type, or does it mean that the declared
> object is the size of its type but is a subobject of a bigger, unnamed
> object that the compiler allocates to accommodate for the initialized
> FAM? The documentation is not completely clear on that, and of course
> C99 is silent on the matter.


In the following the object referenced is also larger than the effective
type of a sub-portion of it (at least twice as large, actually).

int *p = malloc(sizeof *p * 2);
*p = 0; // modify the first half only

In the case of "int[]" vs "int[N]", the "int[]" doesn't make any assumption
on the type of the object referenced, and doesn't need to do that either: As
long as you don't invoke sizeof on it, you can perfectly well use such an
expression to modify array elements.

I *think* that any object of size N bytes is also N*(N+1)/2 objects, each
being different because the start address or size of them is different. What
object is addressed depends on the lvalue you use (which in turn determines
the address and effective type, i.e size). Not sure what object is accessed
by an "T[]" expression though - I could imagine that the size-N object is
addressed. Tho if you have any insights, please lemme hear!
 
Reply With Quote
 
Clive D. W. Feather
Guest
Posts: n/a
 
      11-20-2010
In message <ib4h3f$g0j$>, Marcin Grzegorczyk
<> wrote:
>(that's 6.7.8p2, not p1)
>The constraint is violated because 6.7.2.1p16 says "In most situations,
>the flexible array member is ignored", and nothing in the Standard
>suggests that initialization is one of the "other" situations. At
>least, that seems to be the intent of the rather vague wording.


Perhaps I should have written "except where explicitly stated
otherwise". Sorry.

>As an unfortunate consequence of all that, it is impossible to create
>portably a static object that could be used as a structure with a
>non-empty FAM.


Why "unfortunate"? FAMs are there to legitimize the "struct hack", where
the object is dynamic. If you want a static object with an array at the
end, declare one.

--
Clive D.W. Feather | Home: <>
Mobile: +44 7973 377646 | Web: <http://www.davros.org>
Please reply to the Reply-To address, which is: <>
 
Reply With Quote
 
Clive D. W. Feather
Guest
Posts: n/a
 
      11-20-2010
In message <ibjpmb$658$03$>, "Johannes Schaub (litb)"
<schaub-> wrote:
>It says "subobjects ... are initialized ..." here, and in the following text
>it says "If an array of unknown size is initialized...". These two
>paragraphs fit perfectly together, I think.


However, the FAM isn't an array of unknown size, it's a syntactic
construct that invokes special behaviour.

At least, that's the intention of what I wrote. The bit about "the size
of the structure" in 6.7.2.1p16 indicates that there's no array there.

--
Clive D.W. Feather | Home: <>
Mobile: +44 7973 377646 | Web: <http://www.davros.org>
Please reply to the Reply-To address, which is: <>
 
Reply With Quote
 
Clive D. W. Feather
Guest
Posts: n/a
 
      11-20-2010
In message <ibcoef$d2e$>, Marcin Grzegorczyk
<> wrote:
>> But even that analogy is not very good: in the case of normal arrays,
>> the initializer determines the *type* of the object, and then the size
>> follows from the type in the usual way. In the case of a structure with
>> a FAM, the type of the object is the struct, and the size of that type
>> does not include the array (or at least not necessarily all of it).
>> Since the size of the object, as reported by sizeof, doesn't include the
>> array either, one could argue that the array doesn't really belong to
>> the declared object, but to a larger unnamed object that contains both
>> the struct and the array.

>
>Yeah, that's more or less what 6.7.2.1p16 seems to imply.
>
>When I said "the size of an object" above, I meant the size allocated
>by the compiler (because that was what the post to which I was
>originally replying mentioned), not the size defined by the semantics
>of C99. They need not be the same.


Yes, they must.

If I write:
sometype x;

then sizeof(x) equals sizeof(sometype); see 6.5.3.4.

When I write:

int a [] = { 1, 2, 3, 4 };

then this is actually an abbreviation for:

int a [4] = { 1, 2, 3, 4 };

and the above still holds. The compiler is *not* allowed, in that
situation, to create an object whose size is 6 ints long (though, I
accept, it could be hard to determine whether it had).

--
Clive D.W. Feather | Home: <>
Mobile: +44 7973 377646 | Web: <http://www.davros.org>
Please reply to the Reply-To address, which is: <>
 
Reply With Quote
 
Marcin Grzegorczyk
Guest
Posts: n/a
 
      11-23-2010
Clive D. W. Feather wrote:
> In message<ibcoef$d2e$>, Marcin Grzegorczyk
> <> wrote:
>> When I said "the size of an object" above, I meant the size allocated
>> by the compiler (because that was what the post to which I was
>> originally replying mentioned), not the size defined by the semantics
>> of C99. They need not be the same.

>
> Yes, they must.


Eh, no.
Again, I was referring to the actual implementation. A compiler/linker
obviously can allocate more space for an object than necessary to
represent that object, even if this is rarely (if ever) useful. Of
course, a strictly conforming program has no way of determining if the
implementation does that.
--
Marcin Grzegorczyk
 
Reply With Quote
 
Marcin Grzegorczyk
Guest
Posts: n/a
 
      11-23-2010
Clive D. W. Feather wrote:
> In message <ib4h3f$g0j$>, Marcin Grzegorczyk
> <> wrote:
>> As an unfortunate consequence of all that, it is impossible to create
>> portably a static object that could be used as a structure with a
>> non-empty FAM.

>
> Why "unfortunate"? FAMs are there to legitimize the "struct hack", where
> the object is dynamic. If you want a static object with an array at the
> end, declare one.


I consider it unfortunate because I've come across situations where the
object using the "struct hack" is not at all dynamic (code written for
freestanding implementations without a malloc). If static
initialization of a FAM were a standard feature, in RAM-constrained
systems such objects could be placed in a ROM without sacrificing
portability.

I understand, though, that this feature may be neither widespread enough
(I don't know if any compiler other than GCC supports it) nor useful
enough to warrant its standardization.
--
Marcin Grzegorczyk
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      11-23-2010
Marcin Grzegorczyk <> writes:
> Clive D. W. Feather wrote:
>> In message<ibcoef$d2e$>, Marcin Grzegorczyk
>> <> wrote:
>>> When I said "the size of an object" above, I meant the size allocated
>>> by the compiler (because that was what the post to which I was
>>> originally replying mentioned), not the size defined by the semantics
>>> of C99. They need not be the same.

>>
>> Yes, they must.

>
> Eh, no.
> Again, I was referring to the actual implementation. A compiler/linker
> obviously can allocate more space for an object than necessary to
> represent that object, even if this is rarely (if ever) useful. Of
> course, a strictly conforming program has no way of determining if the
> implementation does that.


An implementation can allocate as much space as it likes that's
associated with an object, but anything beyond ``sizeof object'' bytes
is, at least in one very important sense, not part of "the size of the
object". It could be thought of as padding or overhead.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
python-fam documentation. Shriphani Python 2 07-26-2007 12:39 AM
why why why why why Mr. SweatyFinger ASP .Net 4 12-21-2006 01:15 PM
[ANN] FAM-Ruby 0.2.0 Paul Duncan Ruby 0 12-20-2006 11:25 AM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
Why no compiler-warning at invalid array-initializing ? carlos@gkpwdun.com Java 11 11-07-2005 08:34 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57