PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.c > What's the use of anonymous structs?
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
What's the use of anonymous structs?

Réponse
 
LinkBack Outils de la discussion
Vieux 29/10/2007, 02h02   #26
David Thompson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: What's the use of anonymous structs?

On Thu, 18 Oct 2007 16:29:53 -0700, ymuntyan@gmail.com wrote:

> On Oct 18, 11:18 am, Eric Sosman <Eric.Sos...@sun.com> wrote:
> > ymunt...@gmail.com wrote On 10/18/07 09:37,:


> > No, 6.2.7p1 says they are *compatible* types, not that
> > they are the *same* type.

>
> Well, the "compatible" there is italicized, I take it as
> that's the definition of "compatible". In other words, it


But the definition includes the rest of para 1, and the other paras
referred to; it must, otherwise these statements, which are stated as
requirements in the standard, would be inconsistent with the
definition and thus no implementation of C would be possible. And we
know it can't be the intent of the Standard writers to prevent all
implementations and therefore all use of the language. (In spite of
exaggerated and insulting conspiracy theories from some.)

> says something like "Types are compatible if and only if
> they are the same". And then it goes to explain what it
> means for two types to be "the same".
>

Compatibility is deliberately weaker than being the same.
If two types are the same they are compatible; if they are distinct,
but are _sufficiently similar_ according to the specific rules given
in the rest of para 1 and the other paras, they are compatible.

Informally, compatibility of X and Y means that an (actual) X can
safely be accessed as a Y and it will work. This means compatible
types must have the same layout (representation) in storage, and types
that don't have the same representation can't be compatible. However
the converse (or inverse? I always forget) is not true: there are
(pairs of) types that are required to have the same representation(s),
but are still distinct types so that the compiler can (and usually
must) diagnose type-mixings considered undesirable.

> But it makes stuff like
>
> struct {int a; int b;} a;
> struct {int a; int b;} *p = &a;
>
> illegal, or, more realistic,
>
> void callback (void *p)
> {
> struct {int a; int b;} *data = p;
> /* ... */
> }
>
> void func (void)
> {
> struct {int a; int b;} data = {1, 2};
> call_something (callback, &data);
> }
>

Indeed it does. Declare the struct tag, or a typedef for the untagged
struct, once, somewhere visible to all uses -- which if it is used in
multiple functions means the declaration must be at file scope. That's
the rule. Or if you want to cheat, learn to live with the warnings and
override the errors. That's the way it is.

> // file.h
> extern struct {int a; int b;} *a;
>
> It's impossible to actually define that 'a' if you include
> the header into the C file; and it's possible all right if
> you don't. Weird example of course, and it's why (it's a
> hypothesis) this wasn't taken into account - nobody thought
> about it or it was too much trouble to add it to the standard
> comparing to the benefits.
>

Yes, that's a mildly unfortunate consequence of the rules adopted to
handle the cases considered more important.

This simple but fairly common case -- exactly one variable of or using
the type -- can be done by preprocessor trickery, if init to 0 is OK:

BLECH struct { blah blah } gorp;
where BLECH is #define'd as extern for all #include's of file.h EXCEPT
the one where you want to define the data; there is it #define'd
empty, which makes this a tentative definition, and since there can't
be another compatible declaration with initializer in that t.u. it
becomes an actual definition, and the one definition needed.
(Use a more mnemonic name, of course, depending on which
characteristic you want to emphasize and document: something like
ALLOC_OR_SHARE or something like GLOBAL_SINGLE_DATUM.)

For init to non-0, but known, you can use a macro that generates
either the correct initializer or no initializer.

But more generally you indeed cannot have two anonymous struct types
declared in the same t.u. with the same contents be the same type.

- formerly david.thompson1 || achar(64) || worldnet.att.net
  Réponse avec citation
Vieux 30/10/2007, 23h12   #27
Francine.Neary@googlemail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: What's the use of anonymous structs?

On Oct 18, 4:18 pm, Eric Sosman <Eric.Sos...@sun.com> wrote:
> Cross-module compatibility addresses a nasty issue
> that confronts many separately-compilable languages. If
> the compiler processes module A on Tuesday and processes
> module B on Wednesday, we can't really talk about a type
> compiled in A being "the same" as a type declared in B.
> And yet, we want A to create objects of type T and pass
> them to B to be processed. Since A and B had separate
> declarations for T they can't really have "the same" T,
> so the Standard resorts to this notion of "compatibility"
> to allow separately-compiled modules to agree on what a
> T looks like.


Does that mean that the compiler is obliged to use the same memory
layout (i.e. same amount of padding in the same places) for two
structs with identical fields declared in different translation units?
What about if one of the fields has a different name (but the same
type) in the two structs?

If the answer to the first question is "yes", does that create
practical problems when trying to link object files created with
different C compilers (or the same compiler with different
optimization or other settings)?

>
> --
> Eric.Sos...@sun.com



  Réponse avec citation
Vieux 30/10/2007, 23h32   #28
Eric Sosman
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: What's the use of anonymous structs?

Francine.Neary@googlemail.com wrote On 10/30/07 18:12,:
> On Oct 18, 4:18 pm, Eric Sosman <Eric.Sos...@sun.com> wrote:
>
>> Cross-module compatibility addresses a nasty issue
>>that confronts many separately-compilable languages. If
>>the compiler processes module A on Tuesday and processes
>>module B on Wednesday, we can't really talk about a type
>>compiled in A being "the same" as a type declared in B.
>>And yet, we want A to create objects of type T and pass
>>them to B to be processed. Since A and B had separate
>>declarations for T they can't really have "the same" T,
>>so the Standard resorts to this notion of "compatibility"
>>to allow separately-compiled modules to agree on what a
>>T looks like.

>
>
> Does that mean that the compiler is obliged to use the same memory
> layout (i.e. same amount of padding in the same places) for two
> structs with identical fields declared in different translation units?
> What about if one of the fields has a different name (but the same
> type) in the two structs?


If the struct tags are different, the types are different.
You can test this for yourself:

struct A { int i; } a = { 42 };
struct B { int i; } b;
b = a; /* diagnostic required */

Since the two structs are of different types, they could
in theory have different representations: The Standard requires
common representations for only a few sets of types, and these
are not among them. In practice, though, the compiler will
process the `struct A' and `struct B' declarations with the
same algorithm and get the same result (in the absence of
things like `#pragma pack' and similar bletcherous botches).

> If the answer to the first question is "yes", does that create
> practical problems when trying to link object files created with
> different C compilers (or the same compiler with different
> optimization or other settings)?


There *are* practical problems in linking objects from
different compilers. As for option flags, if they make the
compiler behave differently, then what you've really got is
one piece of software that several different compilers. For
example, if there's a `--pack-all-structs' option, you can
expect trouble mixing modules compiled with and without it.

--
Eric.Sosman@sun.com

  Réponse avec citation
Vieux 30/10/2007, 23h53   #29
Francine.Neary@googlemail.com
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: What's the use of anonymous structs?

On 30 Oct 2007 at 22:32, Eric Sosman wrote:
> Francine.Neary@googlemail.com wrote On 10/30/07 18:12,:
>> Does that mean that the compiler is obliged to use the same memory
>> layout (i.e. same amount of padding in the same places) for two
>> structs with identical fields declared in different translation units?
>> What about if one of the fields has a different name (but the same
>> type) in the two structs?

>
> If the struct tags are different, the types are different.
> You can test this for yourself:
>
> struct A { int i; } a = { 42 };
> struct B { int i; } b;
> b = a; /* diagnostic required */
>
> Since the two structs are of different types, they could
> in theory have different representations: The Standard requires
> common representations for only a few sets of types, and these
> are not among them. In practice, though, the compiler will
> process the `struct A' and `struct B' declarations with the
> same algorithm and get the same result (in the absence of
> things like `#pragma pack' and similar bletcherous botches).


I guess I was asking specifically about un-named structs in different
translation units. Consider the following code:


/* TU1.c */

void foo(struct { int a; })
{
...
}


/* TU2.c */

void foo(struct { int a; });
void bar()
{
struct { int a; } X;
X.a=0;
foo(X);
}


/* TU3.c */

void foo(struct { int a; });
void baz()
{
struct { int a; } Y;
Y.a=0;
foo(Y);
}

If I understood what you said upthread correctly, this will work just
fine, though if foo were actually defined in TU2.c then there'd be a
type-incompatibility and TU2.c wouldn't compile.

Doesn't this force binary compatibility between objects of any unnamed
types struct { int a; } in different translation units? (But not
necessary between an object of a type struct { int a; } and an object
of a type struct { int b; } ?)

  Réponse avec citation
Vieux 31/10/2007, 02h44   #30
Eric Sosman
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: What's the use of anonymous structs?

Francine.Neary@googlemail.com wrote:
> On 30 Oct 2007 at 22:32, Eric Sosman wrote:
>> Francine.Neary@googlemail.com wrote On 10/30/07 18:12,:
>>> Does that mean that the compiler is obliged to use the same memory
>>> layout (i.e. same amount of padding in the same places) for two
>>> structs with identical fields declared in different translation units?
>>> What about if one of the fields has a different name (but the same
>>> type) in the two structs?

>> If the struct tags are different, the types are different.
>> You can test this for yourself:
>>
>> struct A { int i; } a = { 42 };
>> struct B { int i; } b;
>> b = a; /* diagnostic required */
>>
>> Since the two structs are of different types, they could
>> in theory have different representations: The Standard requires
>> common representations for only a few sets of types, and these
>> are not among them. In practice, though, the compiler will
>> process the `struct A' and `struct B' declarations with the
>> same algorithm and get the same result (in the absence of
>> things like `#pragma pack' and similar bletcherous botches).

>
> I guess I was asking specifically about un-named structs in different
> translation units. Consider the following code:
>
>
> /* TU1.c */
>
> void foo(struct { int a; })


Needs an identifier after the } -- let's call it tu1.

> {
> ...
> }
>
>
> /* TU2.c */
>
> void foo(struct { int a; });
> void bar()
> {
> struct { int a; } X;
> X.a=0;
> foo(X);


Diagnostic required. The declared type of the parameter
to foo() is different from that of X, and no conversion is
possible. You've got two untagged struct types in the same
translation unit; the compatibility rule for untagged structs
specifically requires separate translation units.

Within one translation unit, each struct declaration
introduces a new type, distinct from all other types. For
structs with tags the scope rules apply: Two identically-
tagged structs in disjoint scopes are different types, while
two identically-tagged structs in overlapping scopes provoke
a diagnostic. For untagged structs, the behavior is as if
the compiler gave the first one an artificial tag like `#1',
the next one `#2', and so on: Each untagged struct is a distinct
type, no matter what the scope, and two such struct types can
never be compatible.

Some compilers will emit a ful warning about the
declaration of foo(), pointing out that the struct type has
"prototype scope." That is, the type goes out of scope at
the end of the prototype, meaning that any similar struct you
might declare elsewhere will be in a different scope and will
not be of the same type. Thus, there is no way to write a
correct call to foo() in the same translation unit because
there is no way to declare an argument of the proper type.

> }
>
>
> /* TU3.c */
>
> void foo(struct { int a; });
> void baz()
> {
> struct { int a; } Y;
> Y.a=0;
> foo(Y);


Same problem as before: Two untagged structs in the same
translation unit are two distinct types.

> }
>
> If I understood what you said upthread correctly, this will work just
> fine, though if foo were actually defined in TU2.c then there'd be a
> type-incompatibility and TU2.c wouldn't compile.
>
> Doesn't this force binary compatibility between objects of any unnamed
> types struct { int a; } in different translation units? (But not
> necessary between an object of a type struct { int a; } and an object
> of a type struct { int b; } ?)


I think you should re-read 6.2.7p1, and then if necessary
take a deep breath and read it yet again. Question 11.5 in
the FAQ may also be ful.

--
Eric Sosman
esosman@ieee-dot-org.invalid
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 19h20.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières ©2000-2008
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,15212 seconds with 13 queries