Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #30346 > unrolled thread

Struct assignment

Started byRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
First post2013-01-19 23:09 +1100
Last post2013-01-20 12:03 -0800
Articles 20 on this page of 27 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-19 23:09 +1100
    Re: Struct assignment Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-19 08:27 -0500
      Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-20 01:18 +1100
        Re: Struct assignment "BartC" <bc@freeuk.com> - 2013-01-19 14:59 +0000
        Re: Struct assignment Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-19 11:25 -0500
          Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-20 12:46 +1100
            Re: Struct assignment Bart van Ingen Schenau <bart@ingen.ddns.info.invalid> - 2013-01-20 09:20 +0000
            Re: Struct assignment Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-20 09:08 -0500
              Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-21 12:02 +1100
                Re: Struct assignment Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-20 22:08 -0500
                  Re: Struct assignment James Kuyper <jameskuyper@verizon.net> - 2013-01-20 23:21 -0500
                Re: Struct assignment James Kuyper <jameskuyper@verizon.net> - 2013-01-21 08:23 -0500
                  Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-22 13:33 +1100
                  Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-23 19:53 +1100
        Re: Struct assignment Shao Miller <sha0.miller@gmail.com> - 2013-01-19 11:45 -0500
          Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-20 13:21 +1100
            Re: Struct assignment Shao Miller <sha0.miller@gmail.com> - 2013-01-20 01:06 -0500
              Re: Struct assignment Russell Shaw <rjshawN_o@s_pam.netspace.net.au> - 2013-01-20 18:03 +1100
    Re: Struct assignment glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-19 19:18 +0000
      Re: Struct assignment James Kuyper <jameskuyper@verizon.net> - 2013-01-19 15:22 -0500
        Re: Struct assignment Shao Miller <sha0.miller@gmail.com> - 2013-01-19 15:47 -0500
        Re: Struct assignment Eric Sosman <esosman@comcast-dot-net.invalid> - 2013-01-19 17:56 -0500
          Re: Struct assignment Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-20 12:12 -0800
    Re: Struct assignment falk@rahul.net (Edward A. Falk) - 2013-01-19 23:41 +0000
      Re: Struct assignment glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-20 01:01 +0000
      Re: Struct assignment James Kuyper <jameskuyper@verizon.net> - 2013-01-19 20:53 -0500
        Re: Struct assignment Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-20 12:03 -0800

Page 1 of 2  [1] 2  Next page →


#30346 — Struct assignment

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-19 23:09 +1100
SubjectStruct assignment
Message-ID<u0fqs9-929.ln1@main.anatron.com.au>
Hi,
In gcc-4.7 C99, i get an error (in a function scope):

   struct {
       int a;
   } sa;

   struct {
       int a;
   } sb;

   sb = sa;

error: incompatible types when assigning to type 'struct <anonymous>' from type 
'struct <anonymous>'


ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336

6.5.16.1 Simple assignment
Para 1
-- the left operand has a qualified or unqualified version of a structure or 
union type compatible with the type of the right;


6.2.7 Compatible type and composite type
Para 1
Two types have compatible type if their types are the same. Additional rules for 
determining whether two types are compatible are described in 6.7.2 for type 
specifiers, in 6.7.3 for type qualifiers, and in 6.7.5 for declarators.48) 
Moreover, two structure, union, or enumerated types declared in separate 
translation units are compatible if their tags and members satisfy the following 
requirements: If one is declared with a tag, the other shall be declared with 
the same tag. If both are complete types, then the following additional 
requirements apply: there shall be a one-to-one correspondence between their 
members such that each pair of corresponding members are declared with 
compatible types, and such that if one member of a corresponding pair is 
declared with a name, the other member is declared with the same name. For two 
structures, corresponding members shall be declared in the same order. For two 
structures or unions, corresponding bit-fields shall have the same widths. For 
two enumerations, corresponding members shall have the same values.


The above mentions "separate translation units", but i don't see why the error 
should happen.

[toc] | [next] | [standalone]


#30347

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-19 08:27 -0500
Message-ID<kde706$3t0$1@dont-email.me>
In reply to#30346
On 1/19/2013 7:09 AM, Russell Shaw wrote:
> Hi,
> In gcc-4.7 C99, i get an error (in a function scope):
>
>    struct {
>        int a;
>    } sa;
>
>    struct {
>        int a;
>    } sb;
>
>    sb = sa;
>
> error: incompatible types when assigning to type 'struct <anonymous>'
> from type 'struct <anonymous>'
>
>
> ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336
>
> 6.5.16.1 Simple assignment
> Para 1
> -- the left operand has a qualified or unqualified version of a
> structure or union type compatible with the type of the right;
>
>
> 6.2.7 Compatible type and composite type
> Para 1
> Two types have compatible type if their types are the same. Additional
> rules for determining whether two types are compatible are described in
> 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
> for declarators.48) Moreover, two structure, union, or enumerated types
> declared in separate translation units are compatible if their tags and
> members satisfy the following requirements: If one is declared with a
> tag, the other shall be declared with the same tag. If both are complete
> types, then the following additional requirements apply: there shall be
> a one-to-one correspondence between their members such that each pair of
> corresponding members are declared with compatible types, and such that
> if one member of a corresponding pair is declared with a name, the other
> member is declared with the same name. For two structures, corresponding
> members shall be declared in the same order. For two structures or
> unions, corresponding bit-fields shall have the same widths. For two
> enumerations, corresponding members shall have the same values.
>
>
> The above mentions "separate translation units", but i don't see why the
> error should happen.

     Um, er, because your `sa' and `sb' are not in separate
translation units?  And hence aren't compatible?

     The fact that two types look the same (as yours do) doesn't
mean they actually are the same; it's just a coincidence of
their representation.  On many systems `int' and `long' have
the same representation and even the same behavior, yet they
are distinct types nonetheless.  (Incompatible types, too,
though implicit conversions often disguise the fact.)

     Have you ever run into the (in)famous "struct declaration
in parameter list" problem (FAQ Question 2.5)?  That's very much
like what's happening here: Having written a type declaration
without a name (tag) or alias (typedef), you have no way to
designate that same type again.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#30349

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-20 01:18 +1100
Message-ID<simqs9-ue9.ln1@main.anatron.com.au>
In reply to#30347
On 20/01/13 00:27, Eric Sosman wrote:
> On 1/19/2013 7:09 AM, Russell Shaw wrote:
>> Hi,
>> In gcc-4.7 C99, i get an error (in a function scope):
>>
>> struct {
>> int a;
>> } sa;
>>
>> struct {
>> int a;
>> } sb;
>>
>> sb = sa;
>>
>> error: incompatible types when assigning to type 'struct <anonymous>'
>> from type 'struct <anonymous>'
>>
>>
>> ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336
>>
>> 6.5.16.1 Simple assignment
>> Para 1
>> -- the left operand has a qualified or unqualified version of a
>> structure or union type compatible with the type of the right;
>>
>>
>> 6.2.7 Compatible type and composite type
>> Para 1
>> Two types have compatible type if their types are the same. Additional
>> rules for determining whether two types are compatible are described in
>> 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
>> for declarators.48) Moreover, two structure, union, or enumerated types
>> declared in separate translation units are compatible if their tags and
>> members satisfy the following requirements: If one is declared with a
>> tag, the other shall be declared with the same tag. If both are complete
>> types, then the following additional requirements apply: there shall be
>> a one-to-one correspondence between their members such that each pair of
>> corresponding members are declared with compatible types, and such that
>> if one member of a corresponding pair is declared with a name, the other
>> member is declared with the same name. For two structures, corresponding
>> members shall be declared in the same order. For two structures or
>> unions, corresponding bit-fields shall have the same widths. For two
>> enumerations, corresponding members shall have the same values.
>>
>>
>> The above mentions "separate translation units", but i don't see why the
>> error should happen.
>
> Um, er, because your `sa' and `sb' are not in separate
> translation units? And hence aren't compatible?
>
> The fact that two types look the same (as yours do) doesn't
> mean they actually are the same; it's just a coincidence of
> their representation. On many systems `int' and `long' have
> the same representation and even the same behavior, yet they
> are distinct types nonetheless. (Incompatible types, too,
> though implicit conversions often disguise the fact.)
>
> Have you ever run into the (in)famous "struct declaration
> in parameter list" problem (FAQ Question 2.5)? That's very much
> like what's happening here: Having written a type declaration
> without a name (tag) or alias (typedef), you have no way to
> designate that same type again.

Why should it matter that the second struct is "declared" in a separate 
translation unit? To be able to do the assignment, you have to #include that 
second declaration in to the first file anyway.

It's easy to write a compiler to do that assignment deterministically, so why's 
it not allowed?

p.6.2.7 describes the compatability for structs in separate translation units, 
but says nothing (ie, does not forbid) about assignments in the same translation 
unit.

[toc] | [prev] | [next] | [standalone]


#30350

From"BartC" <bc@freeuk.com>
Date2013-01-19 14:59 +0000
Message-ID<RyyKs.8680$ir5.3227@fx11.fr7>
In reply to#30349
"Russell Shaw" <rjshawN_o@s_pam.netspace.net.au> wrote in message 
news:simqs9-ue9.ln1@main.anatron.com.au...

>>> sb = sa;
>>>
>>> error: incompatible types when assigning to type 'struct <anonymous>'
>>> from type 'struct <anonymous>'

> It's easy to write a compiler to do that assignment deterministically, so 
> why's it not allowed?

In general there may be incompatibilities between two structs, so simple 
assignment is not possible or may be dangerous.

You're suggesting the compiler should make a special case of certain pairs 
of structs, and allow assignment, while forbidding it for others. That's an 
untidy way of doing things. It's simpler to insist the structs are exactly 
the same. (And makes maintenance simpler: make a minor change to one of the 
two structs, or use a different pack() value, and suddenly those hundreds of 
sa=sb assignments are illegal. Make the same change to the one struct, and 
all those sa=sb will still work.)

In any case an easy workaround is to use memcpy to copy them, whether they 
are compatible (or even the same size) or not.

-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


#30351

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-19 11:25 -0500
Message-ID<kdehee$3ni$1@dont-email.me>
In reply to#30349
On 1/19/2013 9:18 AM, Russell Shaw wrote:
> On 20/01/13 00:27, Eric Sosman wrote:
>> [...]
>> Have you ever run into the (in)famous "struct declaration
>> in parameter list" problem (FAQ Question 2.5)? That's very much
>> like what's happening here: Having written a type declaration
>> without a name (tag) or alias (typedef), you have no way to
>> designate that same type again.
>
> Why should it matter that the second struct is "declared" in a separate
> translation unit? To be able to do the assignment, you have to #include
> that second declaration in to the first file anyway.

     The point of separate compilation is that the compilations
are, well, separate.  The compiler processes one file on Tuesday
and the other on Wednesday, perhaps even on different machines.
The two declarations are not visible to the compiler at the same
time, so the compiler has no way to connect them.  The compiler
cannot even tell that the declarations were #include'd from the
same file -- or, quite likely, from distinct files with identical
content (Tuesday's compilation on Machine A, Wednesday's on
Machine B with files copied via FTP, say).

     That's why there's a special dispensation for textually
similar type declarations in different translation units: Without
such a rule, separate compilation simply wouldn't work.

     Within a single translation unit, though, things are different.
Two "anonymous" type declarations are treated as distinct types,
even if they bear a strong resemblance.  Yes, this can lead to a
paradox, where two types in Module X are mutually incompatible,
but are both compatible with a single type in Module Y.  Don't
get too hung up over it; just laugh it off and maybe use it as
a trick question to win bets down at the nerd bar.

> It's easy to write a compiler to do that assignment deterministically,
> so why's it not allowed?

     I'm not entirely sure what you mean by this -- but if "it's
easy," go ahead and do it.  Get the gcc source, modify the compiler
to treat duplicated anonymous declarations the way you want, try it
out on assorted code bases, and see where it leads.  If the outcome
is good, your modification can be "prior art" to support a proposal
to the next revision of the Standard.

> p.6.2.7 describes the compatability for structs in separate translation
> units, but says nothing (ie, does not forbid) about assignments in the
> same translation unit.

     6.2.7 doesn't allow or forbid any kind of assignment; the
string "assign" does not even appear there.

     Assignment is covered in 6.5.16, and in 6.5.16.1p1 (second
bullet) you'll find the requirement that struct assignment must
be between compatible types.  *Then* we go back to 6.2.7 to read
the rules on compatibility, and learn that identical anonymous
struct types are compatible only if declared in separate
translation units.  Your pair are not in separate translation
units so that language doesn't apply; the structs are therefore
incompatible and do not satisfy the "shall" of 6.5.16.1.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#30370

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-20 12:46 +1100
Message-ID<bturs9-mi4.ln1@main.anatron.com.au>
In reply to#30351
On 20/01/13 03:25, Eric Sosman wrote:
> On 1/19/2013 9:18 AM, Russell Shaw wrote:
>> On 20/01/13 00:27, Eric Sosman wrote:
>>> [...]
>>> Have you ever run into the (in)famous "struct declaration
>>> in parameter list" problem (FAQ Question 2.5)? That's very much
>>> like what's happening here: Having written a type declaration
>>> without a name (tag) or alias (typedef), you have no way to
>>> designate that same type again.
>>
>> Why should it matter that the second struct is "declared" in a separate
>> translation unit? To be able to do the assignment, you have to #include
>> that second declaration in to the first file anyway.
>
> The point of separate compilation is that the compilations
> are, well, separate. The compiler processes one file on Tuesday
> and the other on Wednesday, perhaps even on different machines.
> The two declarations are not visible to the compiler at the same
> time, so the compiler has no way to connect them. The compiler
> cannot even tell that the declarations were #include'd from the
> same file -- or, quite likely, from distinct files with identical
> content (Tuesday's compilation on Machine A, Wednesday's on
> Machine B with files copied via FTP, say).
>
> That's why there's a special dispensation for textually
> similar type declarations in different translation units: Without
> such a rule, separate compilation simply wouldn't work.
>
> Within a single translation unit, though, things are different.
> Two "anonymous" type declarations are treated as distinct types,
> even if they bear a strong resemblance. Yes, this can lead to a
> paradox, where two types in Module X are mutually incompatible,
> but are both compatible with a single type in Module Y. Don't
> get too hung up over it; just laugh it off and maybe use it as
> a trick question to win bets down at the nerd bar.
>
>> It's easy to write a compiler to do that assignment deterministically,
>> so why's it not allowed?
>
> I'm not entirely sure what you mean by this -- but if "it's
> easy," go ahead and do it. Get the gcc source, modify the compiler
> to treat duplicated anonymous declarations the way you want, try it
> out on assorted code bases, and see where it leads. If the outcome
> is good, your modification can be "prior art" to support a proposal
> to the next revision of the Standard.

I've half done a compiler, so i should know why things are done the way they 
are. Testing what gcc dis-allows is only a secondary way of reading between the 
lines of the standard. Even if the struct assignment is easy to do, i'll only do 
it if the standard allows it.

>> p.6.2.7 describes the compatability for structs in separate translation
>> units, but says nothing (ie, does not forbid) about assignments in the
>> same translation unit.
>
> 6.2.7 doesn't allow or forbid any kind of assignment; the
> string "assign" does not even appear there.
>
> Assignment is covered in 6.5.16, and in 6.5.16.1p1 (second
> bullet) you'll find the requirement that struct assignment must
> be between compatible types. *Then* we go back to 6.2.7 to read
> the rules on compatibility, and learn that identical anonymous
> struct types are compatible only if declared in separate
> translation units. Your pair are not in separate translation
> units so that language doesn't apply; the structs are therefore
> incompatible and do not satisfy the "shall" of 6.5.16.1.

The problem is that if you #include the declaration of an anonymous struct sa 
from a separate translation unit, then the compiler complains about sb = sa.

If you *don't* #include the declaration of an anonymous struct sa from a 
separate translation unit, then the compiler complains that sa isn't declared.

In what use-case can sb = sa be done without complaint?

[toc] | [prev] | [next] | [standalone]


#30385

FromBart van Ingen Schenau <bart@ingen.ddns.info.invalid>
Date2013-01-20 09:20 +0000
Message-ID<kdgctr$88u$1@dont-email.me>
In reply to#30370
On Sun, 20 Jan 2013 12:46:51 +1100, Russell Shaw wrote:

> The problem is that if you #include the declaration of an anonymous
> struct sa from a separate translation unit, then the compiler complains
> about sb = sa.

I get the feeling that you misunderstand what a translation unit is.
As defined in the C standard (C99 clause 5.1.1.1/1), a translation unit 
consists of a source file *after preprocessing*. This means that all 
#include directives have been expanded into the text of the file they 
reference in a translation unit.
Therefor, it is impossible (by definition) to #include a declaration from 
another translation unit.

> 
> If you *don't* #include the declaration of an anonymous struct sa from a
> separate translation unit, then the compiler complains that sa isn't
> declared.
> 
> In what use-case can sb = sa be done without complaint?

You would need three translation units.

//TU1.c
struct {
  int x;
} sa = { 0 };

//TU2.c
struct {
  int x;
} sb = { 1 };

//TU3.c
extern struct {
  int x;
} sa, sb;

void foo(void)
{
  sa = sb;
}

Now, although each of the three anonymous structs is a distinct type, 
they must be treated as compatible types because the compiler never sees 
two of them together in the same translation unit.

Bart v Ingen Schenau

[toc] | [prev] | [next] | [standalone]


#30401

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-20 09:08 -0500
Message-ID<kdgtp3$7n1$1@dont-email.me>
In reply to#30370
On 1/19/2013 8:46 PM, Russell Shaw wrote:
> [... two "identical" struct types are incompatible ...]
>
> The problem is that if you #include the declaration of an anonymous
> struct sa from a separate translation unit, then the compiler complains
> about sb = sa.

     I don't understand this.  A "translation unit" is all of
the source the compiler sees at one time: The original source
file, all the files and headers it #includes, all the files and
headers they in turn #include, all macros defined on compiler
command lines or whatever, ...  If you #include a declaration,
that declaration is part of *the* translation unit; it is not
an interloper from "a separate translation unit."

> If you *don't* #include the declaration of an anonymous struct sa from a
> separate translation unit, then the compiler complains that sa isn't
> declared.

     Same disconnect; I still don't understand you.

> In what use-case can sb = sa be done without complaint?

     I showed a few elsethread; here's one of them again:

	struct { int a; } sa, sb;
	...
	sa.a = 42;
	sb = sa;

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#30428

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-21 12:02 +1100
Message-ID<hmgus9-9b5.ln1@main.anatron.com.au>
In reply to#30401
On 21/01/13 01:08, Eric Sosman wrote:
> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>> [... two "identical" struct types are incompatible ...]
>>
>> The problem is that if you #include the declaration of an anonymous
>> struct sa from a separate translation unit, then the compiler complains
>> about sb = sa.
>
> I don't understand this. A "translation unit" is all of
> the source the compiler sees at one time: The original source
> file, all the files and headers it #includes, all the files and
> headers they in turn #include, all macros defined on compiler
> command lines or whatever, ... If you #include a declaration,
> that declaration is part of *the* translation unit; it is not
> an interloper from "a separate translation unit."

Precisely. Because of that problem, i could not see how declarations from 
separate translation units should be compatible, when including a header with 
the second declaration now becomes a part of the first translation unit anyway, 
thus making the point mute.

I'll go with the interpretation as stated in this group, because it makes for 
less complication in the compiler, and is safer to use.

>> If you *don't* #include the declaration of an anonymous struct sa from a
>> separate translation unit, then the compiler complains that sa isn't
>> declared.
>
> Same disconnect; I still don't understand you.
>
>> In what use-case can sb = sa be done without complaint?
>
> I showed a few elsethread; here's one of them again:
>
> struct { int a; } sa, sb;
> ...
> sa.a = 42;
> sb = sa;
>

[toc] | [prev] | [next] | [standalone]


#30434

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2013-01-20 22:08 -0500
Message-ID<kdibfc$d0q$1@dont-email.me>
In reply to#30428
On 1/20/2013 8:02 PM, Russell Shaw wrote:
> On 21/01/13 01:08, Eric Sosman wrote:
>> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>>> [... two "identical" struct types are incompatible ...]
>>>
>>> The problem is that if you #include the declaration of an anonymous
>>> struct sa from a separate translation unit, then the compiler complains
>>> about sb = sa.
>>
>> I don't understand this. A "translation unit" is all of
>> the source the compiler sees at one time: The original source
>> file, all the files and headers it #includes, all the files and
>> headers they in turn #include, all macros defined on compiler
>> command lines or whatever, ... If you #include a declaration,
>> that declaration is part of *the* translation unit; it is not
>> an interloper from "a separate translation unit."
>
> Precisely. Because of that problem, i could not see how declarations
> from separate translation units should be compatible, when including a
> header with the second declaration now becomes a part of the first
> translation unit anyway, thus making the point mute.

     (s/mute/moot/)

     That's what the special dispensation in 6.2.7 is for: It
says that "lexically identical" [my phrase] structs in separate
translation units are compatible.  You #include the header from
a source file that is part of translation unit A, and again from
a source in TU B, and you then know that the types in A and B
are compatible.  (As mentioned earlier, you don't even need to
#include the very same file in both TU's: you can #include a copy,
or you can copy-and-paste the text, or you can even re-type the
declaration from scratch.  As long as the two declarations in A
and B satisfy 6.2.7, the types are compatible.)

     In a sense, 6.2.7's special dispensation can be viewed as a
hack, a way to get around the limitations of tool sets.  Note the
precision of the language: The types in A and B are "compatible,"
not "the same."  They cannot be "the same" because there is no
UUID for types, no anchor that allows a compiler in California
and a compiler in Cameroon to cooperate -- especially if the two
compilers process their source files in different decades.  Yet
another way of looking at the issue is to realize that types have
no linkage (6.2.2): If they did, the special dispensation would
be unnecessary, but a whole lot of additional tool machinery
would be needed.  6.2.7 is a formalization of "We want separate
compilation, so we need a way for different compilers on different
days in different parts of the world to agree on compatible types,
without inventing a central universal type registry."

     But within a single TU the difficulties of cross-compiler
coordination vanish: It's one compiler on one day looking at one
batch of source, and it needs no special dispensation to figure
out that `struct foo' means the same thing every time it pops up
in a particular scope.  That's why 6.2.7's language doesn't cover
"lexically identical" declarations in a single TU: The need for
the hack doesn't exist, and there's some (smallish) benefit to
type safety in avoiding hacks where hacking isn't required.

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

[toc] | [prev] | [next] | [standalone]


#30436

FromJames Kuyper <jameskuyper@verizon.net>
Date2013-01-20 23:21 -0500
Message-ID<kdifon$fb$1@dont-email.me>
In reply to#30434
On 01/20/2013 10:08 PM, Eric Sosman wrote:
...
>      That's what the special dispensation in 6.2.7 is for: It
> says that "lexically identical" [my phrase] structs in separate
> translation units are compatible.

Just to nit-pick: I would expect things that are "lexically identical"
to have to match token for token, but 6.2.7p1 is (very slightly) more
lenient than that. It doesn't require that member types be the same,
merely "compatible". It doesn't require that alignment specifiers to be
the same, but merely "equivalent". Bit widths do have to be the "same",
but I believe that the expressions used for those widths do not; a width
of 4 is the same as a width of 2*2, even though the first is only one
token, and the second is three.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#30452

FromJames Kuyper <jameskuyper@verizon.net>
Date2013-01-21 08:23 -0500
Message-ID<kdjfhd$moi$2@dont-email.me>
In reply to#30428
On 01/20/2013 08:02 PM, Russell Shaw wrote:
> On 21/01/13 01:08, Eric Sosman wrote:
>> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>>> [... two "identical" struct types are incompatible ...]
>>>
>>> The problem is that if you #include the declaration of an anonymous
>>> struct sa from a separate translation unit, then the compiler complains
>>> about sb = sa.
>>
>> I don't understand this. A "translation unit" is all of
>> the source the compiler sees at one time: The original source
>> file, all the files and headers it #includes, all the files and
>> headers they in turn #include, all macros defined on compiler
>> command lines or whatever, ... If you #include a declaration,
>> that declaration is part of *the* translation unit; it is not
>> an interloper from "a separate translation unit."
> 
> Precisely. Because of that problem, i could not see how declarations from 
> separate translation units should be compatible, when including a header with 
> the second declaration now becomes a part of the first translation unit anyway, 
> thus making the point mute.

I'm not sure I understand your objection. #include is a red herring
here; all that matters is what the translation units contain after all
#include directives have been processed. Therefore, I'll give an example
involving no shared header files (which would, in general, be a bad
coding practice - but then, IMO, so is the use of unnamed struct types).

file declared.c:
    extern struct {unsigned u:4; _Alignas(long long) double d;} a, b;

file defined.c:
    struct {unsigned u:4; _Alignas(_Alignof(long long)) double d;} a, b;

In each file, 'a' is compatible with 'b', despite the fact that they
both have an anonymous struct type, because the same anonymous struct
definition was used to declare both objects.
The one definition rule requires that the external declarations in
declared.c be compatible with the definitions in defined.c, and they
are, but for a different reason: the definitions of the
struct types in the two different translation units meet all of the
requirements of 6.2.7p1:

"If one is declared with a tag, the other shall be declared with the
same tag." - neither one is declared with a tag.

"If both are completed anywhere within their respective translation
units, then the following additional requirements apply: there shall
be a one-to-one correspondence between their members such that each pair
of corresponding members are declared with compatible types; ..." -
There is such a correspondence - the types of the corresponding members
are not merely compatible, but identical.

"... if one member of the pair is declared with an alignment specifier,
the other is declared with an equivalent alignment specifier; ..."
- 'd' is declared with equivalent alignment specifiers in both struct
definitions.

"... and if one member of the pair is declared with a name, the other is
declared with the same name. ..." - for every pair, the names are in
fact the same.

"For two structures, corresponding members shall be declared in the same
order."  - they are declared in the same order.

"For two structures or unions, corresponding bit-fields shall have the
same widths." - 'u' has the same width in both structure definitions.

The key point is that these requirements only render compatible struct
definitions that appear in different translation units. Therefore, even
though the following line define struct types that also meet all of
those requirements, because they occur in the same translation unit,
they define incompatible struct types:

    struct {unsigned u:4; _Alignof(long long) double d;} a;
    struct {unsigned u:4; _Alignof(long long) double d;} b;

This may seem counter-intuitive, but the reason for this difference is
that it was not considered necessary to extend this specification to
include struct types declared in the same translation unit. The standard
already provides three different ways to define structure objects in the
same translation unit to have compatible types: struct tags, typedefs,
or sharing the same anonymous struct definition, as in my example above.
None of those things would be sufficient to allow declarations of struct
types in different translation units to be compatible - it's only
6.2.7p1 that makes that possible.

Note: I don't agree with this decision; I don't see any advantage to
restricting the guarantee of compatibility to structs defined in
different translation units. However, that is what the standard specifies.

> I'll go with the interpretation as stated in this group, because it makes for 
> less complication in the compiler, and is safer to use.

I'm not sure what you consider to be "the interpretation as stated in
this group". Is it compatible with what I've said above?
-- 
James Kuyper

-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#30491

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-22 13:33 +1100
Message-ID<2ca1t9-6c6.ln1@main.anatron.com.au>
In reply to#30452
On 22/01/13 00:23, James Kuyper wrote:
> On 01/20/2013 08:02 PM, Russell Shaw wrote:
>> On 21/01/13 01:08, Eric Sosman wrote:
>>> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>>>> [... two "identical" struct types are incompatible ...]
>>>>

...

>> I'll go with the interpretation as stated in this group, because it makes for
>> less complication in the compiler, and is safer to use.
>
> I'm not sure what you consider to be "the interpretation as stated in
> this group". Is it compatible with what I've said above?

Hi James.K,
Yes. Thankyou for the detailed post.
I just found a "C Rationale" document i haven't read. I'll read that now.

-- 
regards,
Russell Shaw, B.Eng, M.Eng(Research)

[toc] | [prev] | [next] | [standalone]


#30566

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-23 19:53 +1100
Message-ID<32l4t9-mq6.ln1@main.anatron.com.au>
In reply to#30452
On 22/01/13 00:23, James Kuyper wrote:
> On 01/20/2013 08:02 PM, Russell Shaw wrote:
>> On 21/01/13 01:08, Eric Sosman wrote:
>>> On 1/19/2013 8:46 PM, Russell Shaw wrote:
>>>> [... two "identical" struct types are incompatible ...]
>>>>

...

>> I'll go with the interpretation as stated in this group, because it makes for
>> less complication in the compiler, and is safer to use.
>
> I'm not sure what you consider to be "the interpretation as stated in
> this group". Is it compatible with what I've said above?

Hi James.K,
Yes. Thankyou for the detailed post.
I just found a "C Rationale" document i haven't read. I'll read that now.

-- 
regards,
Russell Shaw, B.Eng, M.Eng(Research)

[toc] | [prev] | [next] | [standalone]


#30352

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-19 11:45 -0500
Message-ID<kdeik4$b8s$1@dont-email.me>
In reply to#30349
On 1/19/2013 09:18, Russell Shaw wrote:
> On 20/01/13 00:27, Eric Sosman wrote:
>> On 1/19/2013 7:09 AM, Russell Shaw wrote:
>>> Hi,
>>> In gcc-4.7 C99, i get an error (in a function scope):
>>>
>>> struct {
>>> int a;
>>> } sa;
>>>
>>> struct {
>>> int a;
>>> } sb;
>>>
>>> sb = sa;
>>>
>>> error: incompatible types when assigning to type 'struct <anonymous>'
>>> from type 'struct <anonymous>'
>>>
>>>
>>> ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336
>>>
>>> 6.5.16.1 Simple assignment
>>> Para 1
>>> -- the left operand has a qualified or unqualified version of a
>>> structure or union type compatible with the type of the right;
>>>
>>>
>>> 6.2.7 Compatible type and composite type
>>> Para 1
>>> Two types have compatible type if their types are the same. Additional
>>> rules for determining whether two types are compatible are described in
>>> 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
>>> for declarators.48) Moreover, two structure, union, or enumerated types
>>> declared in separate translation units are compatible if their tags and
>>> members satisfy the following requirements: If one is declared with a
>>> tag, the other shall be declared with the same tag. If both are complete
>>> types, then the following additional requirements apply: there shall be
>>> a one-to-one correspondence between their members such that each pair of
>>> corresponding members are declared with compatible types, and such that
>>> if one member of a corresponding pair is declared with a name, the other
>>> member is declared with the same name. For two structures, corresponding
>>> members shall be declared in the same order. For two structures or
>>> unions, corresponding bit-fields shall have the same widths. For two
>>> enumerations, corresponding members shall have the same values.
>>>
>>>
>>> The above mentions "separate translation units", but i don't see why the
>>> error should happen.
>>
>> Um, er, because your `sa' and `sb' are not in separate
>> translation units? And hence aren't compatible?
>>
>> The fact that two types look the same (as yours do) doesn't
>> mean they actually are the same; it's just a coincidence of
>> their representation. On many systems `int' and `long' have
>> the same representation and even the same behavior, yet they
>> are distinct types nonetheless. (Incompatible types, too,
>> though implicit conversions often disguise the fact.)
>>
>> Have you ever run into the (in)famous "struct declaration
>> in parameter list" problem (FAQ Question 2.5)? That's very much
>> like what's happening here: Having written a type declaration
>> without a name (tag) or alias (typedef), you have no way to
>> designate that same type again.
>
> Why should it matter that the second struct is "declared" in a separate
> translation unit?

The usual tradition for two translation units to use the same 
programmer-defined type is for them to both #include a header that 
defines that type.  But during translation, it's not really the header 
that defines the type, it's the translation unit.  So we need to ask, 
"Is the type used in TU A the same as in TU B?"  The discussion about 
compatible types answers this question.

> To be able to do the assignment, you have to #include
> that second declaration in to the first file anyway.
>

You don't have to #include anything.  You can copy and paste the type's 
definition manually, or the object's or function's declaration/definition.

> It's easy to write a compiler to do that assignment deterministically,
> so why's it not allowed?
>
> p.6.2.7 describes the compatability for structs in separate translation
> units, but says nothing (ie, does not forbid) about assignments in the
> same translation unit.

How can you argue that their types are the same in this circumstance? 
Since the type has no associated identifier, how can you be sure? 
Please consider another simple case (which presents the same issue):

   int main(void) {
       if ((struct { int x; } *) 0 == (struct { int x; } *) 0)
         return 0;
       return 0;
     }

How do you know that these types are the same?  How do you know how many 
padding bytes these two referenced (pointed-to) types have after their 
'x' members?  How do you know the alignment requirements of the 
referenced types?

Suppose you have:

   typedef int tni;
   struct { int size; } apple;
   struct { tni size; } orange;

Should these two objects be considered to have the same type, if we saw 
these in the same translation unit?  It could be that the _intention_ is 
for each to belong to a different domain, and the discussion of 
compatible types helps to prevent against accidental crossing of domains.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#30371

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-20 13:21 +1100
Message-ID<0u0ss9-jv4.ln1@main.anatron.com.au>
In reply to#30352
On 20/01/13 03:45, Shao Miller wrote:
> On 1/19/2013 09:18, Russell Shaw wrote:
>> On 20/01/13 00:27, Eric Sosman wrote:
>>> On 1/19/2013 7:09 AM, Russell Shaw wrote:
>>>> Hi,
>>>> In gcc-4.7 C99, i get an error (in a function scope):
>>>>
>>>> struct {
>>>> int a;
>>>> } sa;
>>>>
>>>> struct {
>>>> int a;
>>>> } sb;
>>>>
>>>> sb = sa;
>>>>
>>>> error: incompatible types when assigning to type 'struct <anonymous>'
>>>> from type 'struct <anonymous>'
>>>>
>>>>
>>>> ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336
>>>>
>>>> 6.5.16.1 Simple assignment
>>>> Para 1
>>>> -- the left operand has a qualified or unqualified version of a
>>>> structure or union type compatible with the type of the right;
>>>>
>>>>
>>>> 6.2.7 Compatible type and composite type
>>>> Para 1
>>>> Two types have compatible type if their types are the same. Additional
>>>> rules for determining whether two types are compatible are described in
>>>> 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
>>>> for declarators.48) Moreover, two structure, union, or enumerated types
>>>> declared in separate translation units are compatible if their tags and
>>>> members satisfy the following requirements: If one is declared with a
>>>> tag, the other shall be declared with the same tag. If both are complete
>>>> types, then the following additional requirements apply: there shall be
>>>> a one-to-one correspondence between their members such that each pair of
>>>> corresponding members are declared with compatible types, and such that
>>>> if one member of a corresponding pair is declared with a name, the other
>>>> member is declared with the same name. For two structures, corresponding
>>>> members shall be declared in the same order. For two structures or
>>>> unions, corresponding bit-fields shall have the same widths. For two
>>>> enumerations, corresponding members shall have the same values.
>>>>
>>>>
>>>> The above mentions "separate translation units", but i don't see why the
>>>> error should happen.
>>>
>>> Um, er, because your `sa' and `sb' are not in separate
>>> translation units? And hence aren't compatible?
>>>
>>> The fact that two types look the same (as yours do) doesn't
>>> mean they actually are the same; it's just a coincidence of
>>> their representation. On many systems `int' and `long' have
>>> the same representation and even the same behavior, yet they
>>> are distinct types nonetheless. (Incompatible types, too,
>>> though implicit conversions often disguise the fact.)
>>>
>>> Have you ever run into the (in)famous "struct declaration
>>> in parameter list" problem (FAQ Question 2.5)? That's very much
>>> like what's happening here: Having written a type declaration
>>> without a name (tag) or alias (typedef), you have no way to
>>> designate that same type again.
>>
>> Why should it matter that the second struct is "declared" in a separate
>> translation unit?
>
> The usual tradition for two translation units to use the same programmer-defined
> type is for them to both #include a header that defines that type. But during
> translation, it's not really the header that defines the type, it's the
> translation unit. So we need to ask, "Is the type used in TU A the same as in TU
> B?" The discussion about compatible types answers this question.

When both sa and sb are declared in the one common header, sb = sa still gives 
the same error.

I just don't see why the point about being compatible between different 
translation units is made, when the same header declaration is going to be used 
in both anyway.

>> To be able to do the assignment, you have to #include
>> that second declaration in to the first file anyway.
>>
>
> You don't have to #include anything. You can copy and paste the type's
> definition manually, or the object's or function's declaration/definition.
>
>> It's easy to write a compiler to do that assignment deterministically,
>> so why's it not allowed?
>>
>> p.6.2.7 describes the compatability for structs in separate translation
>> units, but says nothing (ie, does not forbid) about assignments in the
>> same translation unit.
>
> How can you argue that their types are the same in this circumstance? Since the
> type has no associated identifier, how can you be sure? Please consider another
> simple case (which presents the same issue):
>
> int main(void) {
> if ((struct { int x; } *) 0 == (struct { int x; } *) 0)
> return 0;
> return 0;
> }
>
> How do you know that these types are the same? How do you know how many padding
> bytes these two referenced (pointed-to) types have after their 'x' members? How
> do you know the alignment requirements of the referenced types?

Both types are structurally the same because they're both pointers to structs 
that are built the same way.

I'm assuming those two structs are built the same way with the same padding, 
because if they weren't, the compiler ABI is then randomly inconsistant.

> Suppose you have:
>
> typedef int tni;
> struct { int size; } apple;
> struct { tni size; } orange;
>
> Should these two objects be considered to have the same type, if we saw these in
> the same translation unit? It could be that the _intention_ is for each to
> belong to a different domain, and the discussion of compatible types helps to
> prevent against accidental crossing of domains.

That's what i'd like to see, but i was trying to figure out how assignments 
between them can be done if they come from different translation units.

I cannot devise how sb = sa can be found in any source, where sb and sa have 
separate struct declarations.


The only use case i can think of is:


Translation unit1:

// tu1.h header:
struct {
   int a;
} sb;

struct sb *str_new(void);


// tu1.c
struct {
   int a;
} sa;

struct sa *str_new(void)
{
   struct sa *str = malloc(sizeof(struct sa));
   return str;
}

[toc] | [prev] | [next] | [standalone]


#30375

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-20 01:06 -0500
Message-ID<kdg1ge$me$1@dont-email.me>
In reply to#30371
On 1/19/2013 21:21, Russell Shaw wrote:
> On 20/01/13 03:45, Shao Miller wrote:
>> On 1/19/2013 09:18, Russell Shaw wrote:
>>> On 20/01/13 00:27, Eric Sosman wrote:
>>>> On 1/19/2013 7:09 AM, Russell Shaw wrote:
>>>>> Hi,
>>>>> In gcc-4.7 C99, i get an error (in a function scope):
>>>>>
>>>>> struct {
>>>>> int a;
>>>>> } sa;
>>>>>
>>>>> struct {
>>>>> int a;
>>>>> } sb;
>>>>>
>>>>> sb = sa;
>>>>>
>>>>> error: incompatible types when assigning to type 'struct <anonymous>'
>>>>> from type 'struct <anonymous>'
>>>>>
>>>>>
>>>>> ISO/IEC 9899:201x Committee Draft -- August 11, 2008 WG14/N1336
>>>>>
>>>>> 6.5.16.1 Simple assignment
>>>>> Para 1
>>>>> -- the left operand has a qualified or unqualified version of a
>>>>> structure or union type compatible with the type of the right;
>>>>>
>>>>>
>>>>> 6.2.7 Compatible type and composite type
>>>>> Para 1
>>>>> Two types have compatible type if their types are the same. Additional
>>>>> rules for determining whether two types are compatible are
>>>>> described in
>>>>> 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5
>>>>> for declarators.48) Moreover, two structure, union, or enumerated
>>>>> types
>>>>> declared in separate translation units are compatible if their tags
>>>>> and
>>>>> members satisfy the following requirements: If one is declared with a
>>>>> tag, the other shall be declared with the same tag. If both are
>>>>> complete
>>>>> types, then the following additional requirements apply: there
>>>>> shall be
>>>>> a one-to-one correspondence between their members such that each
>>>>> pair of
>>>>> corresponding members are declared with compatible types, and such
>>>>> that
>>>>> if one member of a corresponding pair is declared with a name, the
>>>>> other
>>>>> member is declared with the same name. For two structures,
>>>>> corresponding
>>>>> members shall be declared in the same order. For two structures or
>>>>> unions, corresponding bit-fields shall have the same widths. For two
>>>>> enumerations, corresponding members shall have the same values.
>>>>>
>>>>>
>>>>> The above mentions "separate translation units", but i don't see
>>>>> why the
>>>>> error should happen.
>>>>
>>>> Um, er, because your `sa' and `sb' are not in separate
>>>> translation units? And hence aren't compatible?
>>>>
>>>> The fact that two types look the same (as yours do) doesn't
>>>> mean they actually are the same; it's just a coincidence of
>>>> their representation. On many systems `int' and `long' have
>>>> the same representation and even the same behavior, yet they
>>>> are distinct types nonetheless. (Incompatible types, too,
>>>> though implicit conversions often disguise the fact.)
>>>>
>>>> Have you ever run into the (in)famous "struct declaration
>>>> in parameter list" problem (FAQ Question 2.5)? That's very much
>>>> like what's happening here: Having written a type declaration
>>>> without a name (tag) or alias (typedef), you have no way to
>>>> designate that same type again.
>>>
>>> Why should it matter that the second struct is "declared" in a separate
>>> translation unit?
>>
>> The usual tradition for two translation units to use the same
>> programmer-defined
>> type is for them to both #include a header that defines that type. But
>> during
>> translation, it's not really the header that defines the type, it's the
>> translation unit. So we need to ask, "Is the type used in TU A the
>> same as in TU
>> B?" The discussion about compatible types answers this question.
>
> When both sa and sb are declared in the one common header, sb = sa still
> gives the same error.
>

Agreed.

> I just don't see why the point about being compatible between different
> translation units is made, when the same header declaration is going to
> be used in both anyway.
>

This doesn't quite make sense to me.  If you have one .h file that 
declares two objects, can you please explain:

   - In which .c file will 'sa' be defined?
   - In which .c file will 'sb' be defined?
   - In which .c file will the assignment occur?

I'm not sure which scenario you're imagining.

>>> To be able to do the assignment, you have to #include
>>> that second declaration in to the first file anyway.
>>>
>>
>> You don't have to #include anything. You can copy and paste the type's
>> definition manually, or the object's or function's
>> declaration/definition.
>>

Did you spot this part, above?

>>> It's easy to write a compiler to do that assignment deterministically,
>>> so why's it not allowed?
>>>
>>> p.6.2.7 describes the compatability for structs in separate translation
>>> units, but says nothing (ie, does not forbid) about assignments in the
>>> same translation unit.
>>
>> How can you argue that their types are the same in this circumstance?
>> Since the
>> type has no associated identifier, how can you be sure? Please
>> consider another
>> simple case (which presents the same issue):
>>
>> int main(void) {
>> if ((struct { int x; } *) 0 == (struct { int x; } *) 0)
>> return 0;
>> return 0;
>> }
>>
>> How do you know that these types are the same? How do you know how
>> many padding
>> bytes these two referenced (pointed-to) types have after their 'x'
>> members? How
>> do you know the alignment requirements of the referenced types?
>
> Both types are structurally the same because they're both pointers to
> structs that are built the same way.
>

There are plenty of types whose representation and alignment 
requirements match.  Does that mean that they should be interchangeable? 
  That was the point of my "apples" and "oranges" example, just below. 
Type is something more than representation and alignment.  It means you 
can say "these things are different than these other things, and should 
not be mixed up."  How would you ensure that things don't get mixed up 
inappropriately if representation and alignment was good enough for 
compatibility?

> I'm assuming those two structs are built the same way with the same
> padding, because if they weren't, the compiler ABI is then randomly
> inconsistant.
>

Yes, I'd agree that you're probably right close to 100% of the time, 
especially due to the "common initial sequence" discussion for unions 
and due to the compatibility requirement across translation units.  I 
think a problem is your use of "ABI", which doesn't have a meaning in 
the Standard.

>> Suppose you have:
>>
>> typedef int tni;
>> struct { int size; } apple;
>> struct { tni size; } orange;
>>
>> Should these two objects be considered to have the same type, if we
>> saw these in
>> the same translation unit? It could be that the _intention_ is for
>> each to
>> belong to a different domain, and the discussion of compatible types
>> helps to
>> prevent against accidental crossing of domains.
>
> That's what i'd like to see,

That's not what _I'd_ like to see!  I want type safety that allows me to 
specify different domains of values, without any care for internal 
representational co-incidences.  I don't want to accidentally compare 
apples and oranges.

> but i was trying to figure out how
> assignments between them can be done if they come from different
> translation units.
>

Translation unit #1:

   struct { int i; double d; } foo;

Translation unit #2:

   extern struct { int i; double d; } foo;

Now the type of 'foo' in TU #1 can be said to be compatible with the 
type in TU #2.

> I cannot devise how sb = sa can be found in any source, where sb and sa
> have separate struct declarations.
>

Why you are searching for such a case?  Type compatibility is used in a 
lot of places other than assignment.  As just one example, suppose you have:

Translation unit #1:

   static struct { int i; double d; } foo;
   void * foo_ptr = &foo;

   void callme(void) {
       if (foo.i == 42 && foo.d == 3.14159)
         /* Success */
         return;
     }

Translation unit #2:

   extern void callme(void);
   extern void * foo_ptr;

   static struct { int i; double d; } bar;

   static void somefunc(void) {
       bar.i = 42;
       bar.d = 3.14159;
       memcpy(foo_ptr, &bar, sizeof bar);
       callme();
     }

If 'foo' and 'bar' didn't have compatible types, then when 'somefunc' 
calls 'callme' and 'callme' tries to read the value of 'foo.i' and 
'foo.d', it'd be undefined behaviour.  Because they have compatible 
types, things are ok.

>
> The only use case i can think of is:
>
>
> Translation unit1:
>
> // tu1.h header:
> struct {
>    int a;
> } sb;
>
> struct sb *str_new(void);
>
>
> // tu1.c
> struct {
>    int a;
> } sa;
>
> struct sa *str_new(void)
> {
>    struct sa *str = malloc(sizeof(struct sa));
>    return str;
> }

I don't quite follow the point of this code.

(Minor note: The pattern:

   obj_type * ptr = malloc(sizeof *ptr);

says "Allocate enough storage for the pointee" whereas your version says 
"Allocate enough storage for obj_type", which happens to match the right 
size for the pointee.)

Here is a thought experiment:

Imagine that 9 out of 10 people want:

   struct { int i; } root;

to represent a one-of-a-kind object, that should never be compared with 
any other object, even if there is an object like:

   struct { int i; } starting_point;

Now imagine that you need to be able to access 'root' from any other 
translation unit.  You can make a header for those _other_ translation 
units:

   extern struct { int i; } root;

Because the header is actually part of each of the other translation 
units, type compatibility says that the all of the translation units 
think that 'root' is the same type.

Here is a different thought experiment:

Imagine that 1 out of 10 people want:

   struct { int i; } count;

and:

   struct { int i; } number;

to have the same type because they have the same composition, and want 
to be able to assign the values of these objects to one another because 
both are objects that might make sense in the same domain.

Now imagine that 1 out of 10 people see a strange rule that seems to 
interfere with this goal, but seems to allow it when the objects are in 
different translation units.  In fact, if the two objects are declared 
in two translation units (as a header #inclusion would do), the 
allowance doesn't even have any benefit for the goal!

But the two sets of people in these thought experiments have different 
goals.  These thought experiments aren't offered as an actual 
representation of the world, but as a possible way to understand how 
people with different goals can view the rules very differently.

(The 9 people might say to the 1 person, "so identify the type so it can 
be re-used, then we both win, to an extent.")

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#30378

FromRussell Shaw <rjshawN_o@s_pam.netspace.net.au>
Date2013-01-20 18:03 +1100
Message-ID<kehss9-lo7.ln1@main.anatron.com.au>
In reply to#30375
On 20/01/13 17:06, Shao Miller wrote:
> On 1/19/2013 21:21, Russell Shaw wrote:
>> On 20/01/13 03:45, Shao Miller wrote:
>>> On 1/19/2013 09:18, Russell Shaw wrote:
>>>> On 20/01/13 00:27, Eric Sosman wrote:
>>>>> On 1/19/2013 7:09 AM, Russell Shaw wrote:
>>>>>> Hi,
>>>>>> In gcc-4.7 C99, i get an error (in a function scope):
>>>>>>
...
>>> Suppose you have:
>>>
>>> typedef int tni;
>>> struct { int size; } apple;
>>> struct { tni size; } orange;
>>>
>>> Should these two objects be considered to have the same type, if we saw
>>> these in the same translation unit? It could be that the _intention_ is
>>> for each to belong to a different domain, and the discussion of
>>> compatible types helps to prevent against accidental crossing of
>>> domains.
>>
>> That's what i'd like to see,
>
> That's not what _I'd_ like to see! I want type safety that allows me to specify
> different domains of values, without any care for internal representational
> co-incidences. I don't want to accidentally compare apples and oranges.

That's what i meant (the safer option).

>> but i was trying to figure out how assignments between them can be done if
>> they come from different translation units.
>
> Translation unit #1:
>
> struct { int i; double d; } foo;
>
> Translation unit #2:
>
> extern struct { int i; double d; } foo;
>
> Now the type of 'foo' in TU #1 can be said to be compatible with the type in TU #2.
>
>> I cannot devise how sb = sa can be found in any source, where sb and sa
>> have separate struct declarations.
>>
> Why you are searching for such a case?

Just to see if it should be possible or not (i'm doing a compiler).

> Type compatibility is used in a lot of places other than assignment. As just
> one example, suppose you have:
>
> Translation unit #1:
>
> static struct { int i; double d; } foo;
> void * foo_ptr = &foo;
>
> void callme(void) {
> if (foo.i == 42 && foo.d == 3.14159)
> /* Success */
> return;
> }
>
> Translation unit #2:
>
> extern void callme(void);
> extern void * foo_ptr;
>
> static struct { int i; double d; } bar;
>
> static void somefunc(void) {
> bar.i = 42;
> bar.d = 3.14159;
> memcpy(foo_ptr, &bar, sizeof bar);
> callme();
> }
>
> If 'foo' and 'bar' didn't have compatible types, then when 'somefunc' calls
> 'callme' and 'callme' tries to read the value of 'foo.i' and 'foo.d', it'd be
> undefined behaviour. Because they have compatible types, things are ok.
>
>>
>> The only use case i can think of is:
>>
>>
>> Translation unit1:
>>
>> // tu1.h header:
>> struct {
>> int a;
>> } sb;
>>
>> struct sb *str_new(void);
>>
>>
>> // tu1.c
>> struct {
>> int a;
>> } sa;
>>
>> struct sa *str_new(void)
>> {
>> struct sa *str = malloc(sizeof(struct sa));
>> return str;
>> }
>
> I don't quite follow the point of this code.
>
> (Minor note: The pattern:
>
> obj_type * ptr = malloc(sizeof *ptr);
>
> says "Allocate enough storage for the pointee" whereas your version says
> "Allocate enough storage for obj_type", which happens to match the right size
> for the pointee.)
>
> Here is a thought experiment:
>
> Imagine that 9 out of 10 people want:
>
> struct { int i; } root;
>
> to represent a one-of-a-kind object, that should never be compared with any
> other object, even if there is an object like:
>
> struct { int i; } starting_point;
>
> Now imagine that you need to be able to access 'root' from any other translation
> unit. You can make a header for those _other_ translation units:
>
> extern struct { int i; } root;
>
> Because the header is actually part of each of the other translation units, type
> compatibility says that the all of the translation units think that 'root' is
> the same type.
>
> Here is a different thought experiment:
>
> Imagine that 1 out of 10 people want:
>
> struct { int i; } count;
>
> and:
>
> struct { int i; } number;
>
> to have the same type because they have the same composition, and want to be
> able to assign the values of these objects to one another because both are
> objects that might make sense in the same domain.
>
> Now imagine that 1 out of 10 people see a strange rule that seems to interfere
> with this goal, but seems to allow it when the objects are in different
> translation units. In fact, if the two objects are declared in two translation
> units (as a header #inclusion would do), the allowance doesn't even have any
> benefit for the goal!
>
> But the two sets of people in these thought experiments have different goals.
> These thought experiments aren't offered as an actual representation of the
> world, but as a possible way to understand how people with different goals can
> view the rules very differently.
>
> (The 9 people might say to the 1 person, "so identify the type so it can be
> re-used, then we both win, to an extent.")

I'll implement the safer option. The standard is a bit ambiguous without the 
context of existing "practice".

[toc] | [prev] | [next] | [standalone]


#30355

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2013-01-19 19:18 +0000
Message-ID<kderik$f18$2@speranza.aioe.org>
In reply to#30346
Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:

> In gcc-4.7 C99, i get an error (in a function scope):
 
>   struct {
>       int a;
>   } sa;
 
>   struct {
>       int a;
>   } sb;
> 
>   sb = sa;
 
> error: incompatible types when assigning to type 
> 'struct <anonymous>' from type 'struct <anonymous>'

Does the problem go away if you name the structs?
(different names)

-- glen

[toc] | [prev] | [next] | [standalone]


#30356

FromJames Kuyper <jameskuyper@verizon.net>
Date2013-01-19 15:22 -0500
Message-ID<kdev9s$ssf$1@dont-email.me>
In reply to#30355
On 01/19/2013 02:18 PM, glen herrmannsfeldt wrote:
> Russell Shaw <rjshawN_o@s_pam.netspace.net.au> wrote:
> 
>> In gcc-4.7 C99, i get an error (in a function scope):
>  
>>   struct {
>>       int a;
>>   } sa;
>  
>>   struct {
>>       int a;
>>   } sb;
>>
>>   sb = sa;
>  
>> error: incompatible types when assigning to type 
>> 'struct <anonymous>' from type 'struct <anonymous>'
> 
> Does the problem go away if you name the structs?
> (different names)

The two struct types remain incompatible even if named.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web