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


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

Aliasing and subtyping structs

Started byAndreas <nospam@invalid.invalid>
First post2016-11-01 13:15 +0100
Last post2016-12-14 10:14 -0800
Articles 20 on this page of 60 — 16 participants

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


Contents

  Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-01 13:15 +0100
    Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-01 13:34 +0100
      Re: Aliasing and subtyping structs Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-01 15:27 +0000
        Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-02 09:47 +0100
          Re: Aliasing and subtyping structs Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-02 15:47 +0000
            Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-08 00:24 +0100
              Re: Aliasing and subtyping structs supercat@casperkitty.com - 2016-11-07 21:42 -0800
          Re: Aliasing and subtyping structs <william@wilbur.25thandClement.com> - 2016-11-03 18:53 -0700
            Re: Aliasing and subtyping structs supercat@casperkitty.com - 2016-11-04 09:56 -0700
            Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-08 21:53 +0100
    Re: Aliasing and subtyping structs James Kuyper <jameskuyper@verizon.net> - 2016-11-01 11:41 -0400
      Re: Aliasing and subtyping structs Andreas <nospam@invalid.invalid> - 2016-11-02 09:55 +0100
    "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-21 16:59 +0300
      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-21 07:32 -0800
      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-21 11:15 -0500
        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-21 08:35 -0800
          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-22 11:42 +0300
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 06:50 -0800
              Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-22 16:07 +0000
                Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 12:02 -0800
                  Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-11-22 23:36 +0000
                    Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 16:24 -0800
                      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Richard Damon <Richard@Damon-Family.org> - 2016-11-22 22:21 -0500
                        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-23 08:31 -0800
                          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] me <crisdunbar@gmail.com> - 2016-11-23 09:01 -0800
                            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-23 12:05 -0800
        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-11-22 23:23 +0300
          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-22 16:02 -0500
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-22 14:13 -0800
              Re: container_of() macro Noob <root@127.0.0.1> - 2016-11-23 01:10 +0100
                Re: container_of() macro <william@wilbur.25thandClement.com> - 2016-11-22 20:10 -0800
                  Re: container_of() macro "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 15:10 -0800
                Re: container_of() macro David Brown <david.brown@hesbynett.no> - 2016-11-23 11:31 +0100
                  Re: container_of() macro Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-23 14:07 +0300
                  Re: container_of() macro supercat@casperkitty.com - 2016-11-23 08:41 -0800
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-11-30 00:14 +0300
              Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-11-29 17:23 -0500
                Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-04 18:48 +0300
                  Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-04 12:17 -0500
                    Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-04 22:15 +0300
                      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-04 15:06 -0500
                        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@gmail.com> - 2016-12-12 22:31 +0300
      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 13:39 -0800
        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] luser droog <luser.droog@gmail.com> - 2016-11-23 15:10 -0800
          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-23 15:13 -0800
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] luser droog <luser.droog@gmail.com> - 2016-11-23 18:29 -0800
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Anton Shepelev <anton.txt@g{oogle}mail.com> - 2016-11-24 11:41 +0300
            Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-24 03:29 -0800
              Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-24 17:37 -0800
                Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-25 09:55 -0800
                Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-25 15:22 -0800
                  Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-11-28 18:18 -0800
                    Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-29 04:48 -0800
                      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-29 07:28 -0800
                        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-11-30 08:26 -0800
                          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] supercat@casperkitty.com - 2016-11-30 09:13 -0800
                      Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-12 16:44 -0800
                        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Melzzzzz <mel@zzzzz.com> - 2016-12-13 02:18 +0100
                        Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-12-14 09:47 -0800
                          Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs] Thiago Adams <thiago.adams@gmail.com> - 2016-12-14 10:14 -0800

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#97319 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-11-22 23:36 +0000
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<8737ijxf2e.fsf@bsb.me.uk>
In reply to#97303
supercat@casperkitty.com writes:

> On Tuesday, November 22, 2016 at 10:07:39 AM UTC-6, Ben Bacarisse wrote:
>> supercat writes:
>> <snip>
>> > C74
>> 
>> What's that?  Do you have a reference for it?
>
> Sorry--I thought you'd seen other posts where I've used the term previously
> as an informal name for the language described by the 1974 C Reference
> Manual.

Ah, right, pre-K&R C.  Not a language I'd like to go back to.  From what
you go on to say I don't think you do either.  I sounds like you want
some tailored mash-up that fits your view of what C should be.

<snip>
-- 
Ben.

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


#97324 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

Fromsupercat@casperkitty.com
Date2016-11-22 16:24 -0800
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<56c1752f-53c2-425e-8bd9-cb94d6efc9bb@googlegroups.com>
In reply to#97319
On Tuesday, November 22, 2016 at 5:36:36 PM UTC-6, Ben Bacarisse wrote:
> supercat writes:
> Ah, right, pre-K&R C.  Not a language I'd like to go back to.  From what
> you go on to say I don't think you do either.  I sounds like you want
> some tailored mash-up that fits your view of what C should be.

I am of the opinion that later versions of languages should strive to be
supersets of earlier versions whenever practical.  If earlier features
become too expensive to support by default the solution is to define a
means by which programs can indicate when/whether they need support for
the features in question; in some cases that may be accomplished by adding
a "language-version" directive and then specifying that code which states
that it is written for language version X or later must not use feature Y
unless it explicitly specifies that it does so.

Voila--old code continues to work as it always has, new code that doesn't
need to use the features in question can be compiled with optimizations
that would break older code, and code that needs the features can be marked
to block optimizations in the few places they'd be problematic while
allowing them everywhere else.

In what way would that not be a preferable state of affairs to what exists
now?  For many possible behavioral guarantees, there will be some programs
where they have a high cost and no benefit, and others where they have ZERO
cost but significant benefit.  Rather than trying to forge some horrible
compromise, it would be much more helpful to simply let code *specify* which
guarantees it needs.

To allow for the possibility that some platforms might not be capable of
supporting some guarantees, implementations would have the option to
refuse compilation of code requiring them.  A compiler that refuses to
compile any program that requires any guarantee beyond the minimums could
be conforming, but would likely be regarded as being of poor quality.  What
would be important would be that use of the features would never result in
UB.  Either they would work as expected, or compilation would fail outright.
Both situation are vastly preferable to generating machine code which does
not meet requirements.

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


#97326 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromRichard Damon <Richard@Damon-Family.org>
Date2016-11-22 22:21 -0500
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<8X7Zz.63075$WD2.5011@fx35.iad>
In reply to#97324
On 11/22/16 7:24 PM, supercat@casperkitty.com wrote:
> On Tuesday, November 22, 2016 at 5:36:36 PM UTC-6, Ben Bacarisse wrote:
>> supercat writes:
>> Ah, right, pre-K&R C.  Not a language I'd like to go back to.  From what
>> you go on to say I don't think you do either.  I sounds like you want
>> some tailored mash-up that fits your view of what C should be.
>
> I am of the opinion that later versions of languages should strive to be
> supersets of earlier versions whenever practical.  If earlier features
> become too expensive to support by default the solution is to define a
> means by which programs can indicate when/whether they need support for
> the features in question; in some cases that may be accomplished by adding
> a "language-version" directive and then specifying that code which states
> that it is written for language version X or later must not use feature Y
> unless it explicitly specifies that it does so.
>
> Voila--old code continues to work as it always has, new code that doesn't
> need to use the features in question can be compiled with optimizations
> that would break older code, and code that needs the features can be marked
> to block optimizations in the few places they'd be problematic while
> allowing them everywhere else.
>
> In what way would that not be a preferable state of affairs to what exists
> now?  For many possible behavioral guarantees, there will be some programs
> where they have a high cost and no benefit, and others where they have ZERO
> cost but significant benefit.  Rather than trying to forge some horrible
> compromise, it would be much more helpful to simply let code *specify* which
> guarantees it needs.
>
> To allow for the possibility that some platforms might not be capable of
> supporting some guarantees, implementations would have the option to
> refuse compilation of code requiring them.  A compiler that refuses to
> compile any program that requires any guarantee beyond the minimums could
> be conforming, but would likely be regarded as being of poor quality.  What
> would be important would be that use of the features would never result in
> UB.  Either they would work as expected, or compilation would fail outright.
> Both situation are vastly preferable to generating machine code which does
> not meet requirements.
>

If you look at how the Standards Committee has worked on the Standard, 
backwards compatibility HAS been a key point. If the Standard mandated a 
certain behavior for a code sequence, they try very hard to not change 
that, and in cases where the previous standard has left behavior 
undefined or implementation defined, they try hard to not mandate 
behavior in a way incompatible with a real existing implementation.

What they haven't required is that an implementation when it becomes a 
new implementation (maybe implementing a new version of the standard) be 
backwards compatible with its previous non-standard required behavior, 
in part because they ARE different implementations (and in fact, most 
'implementations' are really to the standard a whole lot of different 
implementations based on the option flags given when processing, many of 
which may actually be non-conforming).

Most of the 'additional guarantees' that you would like to see, actually 
to the standard process would be great things for a supplemental 
standard (in the vain of POSIX), which provide limitations to the 
implementations and promises to the user beyond the base C standard, as 
an extension.

The Standards Committee has been somewhat reluctant to add 'optional' 
features to the Standard (though it does have a few, normally for 
special reasons). I suspect that since what you are looking for fits so 
nicely as an extension, I can't see it likely for them to add a bunch of 
new optional features to the base Standard.

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


#97349 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

Fromsupercat@casperkitty.com
Date2016-11-23 08:31 -0800
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<08d60868-93fd-4a5e-927d-5533d701a3fe@googlegroups.com>
In reply to#97326
On Tuesday, November 22, 2016 at 9:21:52 PM UTC-6, Richard Damon wrote:
> If you look at how the Standards Committee has worked on the Standard, 
> backwards compatibility HAS been a key point. If the Standard mandated a 
> certain behavior for a code sequence, they try very hard to not change 
> that, and in cases where the previous standard has left behavior 
> undefined or implementation defined, they try hard to not mandate 
> behavior in a way incompatible with a real existing implementation.

If the C89 Standard Committee was trying to maintain backward compatibility
(I believe they were) that would imply that they did not expect that
describing formerly-defined actions as invoking "Undefined Behavior" would
break programs that relied upon them.  Implementations would be free, after
all, to keep on handling those actions in useful fashion whether or not the
Standard mandated such treatment.

I think the difficulty is that the Committee's actions have been
reinterpreted as a decision to break code which used those behaviors.  The
1974 document (which I think represents the best definition of what the C
language was in 1974) clearly and unambiguously defines semantics which are
sometimes useful, but are not available in the language defined by today's
Standard.  At what point, if ever, was there a conscious decision to remove
them, or was there instead a progression where one version of the Standard
didn't think it necessary to mandate them since compilers universally
supported them anyway, and then a later version of the Standard was drawn
from the perspective that the language had never supported the behaviors?

> What they haven't required is that an implementation when it becomes a 
> new implementation (maybe implementing a new version of the standard) be 
> backwards compatible with its previous non-standard required behavior, 
> in part because they ARE different implementations (and in fact, most 
> 'implementations' are really to the standard a whole lot of different 
> implementations based on the option flags given when processing, many of 
> which may actually be non-conforming).

I think they expected that if existing implementations for machines with
some characteristic [e.g. 16-bit big-endian silent-wraparound two's-
complement, using 32-bit linear pointers] naturally supported certain
useful semantics, future implementations for similar platforms would
naturally support those same behaviors.  Compilers might offer various
options to loosen up behavioral guarantees, but quality implementations
should try to make clear what guarantees would be waived by which options,
and should ensure that old semantics remain available.

For example, a compiler might treat signed integer types as being implicitly
promotable to larger types (which could be larger than any types available
to the user).  Given "int i1,i2; long L1,L2;" a compiler might transform
"L1=i1*i2;" into "L1=(long)i1*i2;" or "L1+1 > L2" into "L1 >= L2", but
allow code to force wrapping semantics with "L1=(int)(i1*i2);" or
"(long)(L1+1) > L2".  Note that compilers wouldn't have to reach very far
to apply the former transforms, and that the use of casts to block them is
analogous to what's required in floating-point when using platforms that
don't promise to refrain from using extra precision during computations
[e.g. given "float f=16777216.0f; double d1=f+1.0f, d2=(float)(f+1.0f);"
the value of d1 might be 16777217.0f, but d2 would be 16777216.0f].

> Most of the 'additional guarantees' that you would like to see, actually 
> to the standard process would be great things for a supplemental 
> standard (in the vain of POSIX), which provide limitations to the 
> implementations and promises to the user beyond the base C standard, as 
> an extension.

A problem I think is that people writing documentation seldom bother to
specify things which they consider obvious.  How many shirt catalogs
explicitly promise that shirts have two sleeves on opposite sides?

> The Standards Committee has been somewhat reluctant to add 'optional' 
> features to the Standard (though it does have a few, normally for 
> special reasons). I suspect that since what you are looking for fits so 
> nicely as an extension, I can't see it likely for them to add a bunch of 
> new optional features to the base Standard.

For the "Standard" to really qualify as a standard, it should define classes
of things such that knowing that x is in class X and knowing that y is in
class Y will allow one to predict something useful about the interaction of
objects x and y.  By that definition, the so-called C "Standard" is only
applicable to programs with constraint violations (which generally aren't
very useful).

Recognizing optional behaviors would greatly increase the value of the
Standard by making it possible and practical to define two very useful
categories of implementations and programs and a couple of useful guarantees
related to them:

  If an implementation which is *at least* Minimally Conforming [satisfying
  requirements somewhat looser than what the Standard presently mandates]
  is fed a Selectively Conforming program, it would be required to either
  run the program without UB or fail in Implementation-Defined fashion.

  If an implementation which is Conforming is fed a Strictly-Conforming
  program [which satisfies a couple of additional requirements beyond what
  would be required under the present standard(*)] it will run the program
  successfully.

(*) Among other things, for a program to be strictly conforming, it would
    be required to include a directive mandating either static or run-time
    stack checking, and if a program which specifies static checking uses
    recursion, it would need to include directives that promise a limit
    to recursive nesting.  This would eliminate stack overflow as a possible
    cause of UB for strictly-conforming programs.

While many tasks cannot be done by Strictly Conforming programs, and the
Standard does not provide any guarantee that even Strictly Conforming
programs will run without UB on more than one implementation, adding
optional behaviors to the Standard would make it possible to greatly expand
the range of programs to which the Standard would apply, and offer an
extremely useful guarantee about their behavior.

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


#97351 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

Fromme <crisdunbar@gmail.com>
Date2016-11-23 09:01 -0800
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<a6c8c092-7107-4ef0-91fd-69742b289ed8@googlegroups.com>
In reply to#97349
On Wednesday, November 23, 2016 at 8:31:33 AM UTC-8, supe...@casperkitty.com wrote:
> On Tuesday, November 22, 2016 at 9:21:52 PM UTC-6, Richard Damon wrote:
> > If you look at how the Standards Committee has worked on the Standard, 
> > backwards compatibility HAS been a key point. If the Standard mandated a 
> > certain behavior for a code sequence, they try very hard to not change 
> > that, and in cases where the previous standard has left behavior 
> > undefined or implementation defined, they try hard to not mandate 
> > behavior in a way incompatible with a real existing implementation.
> 
> If the C89 Standard Committee was trying to maintain backward compatibility
> (I believe they were) that would imply that they did not expect that
> describing formerly-defined actions as invoking "Undefined Behavior" would
> break programs that relied upon them.  Implementations would be free, after
> all, to keep on handling those actions in useful fashion whether or not the
> Standard mandated such treatment.

In a very real way, _nothing_ had defined behaviour before the standard,
so claiming that formerly defined behaviour changed to undefined doesn't
make sense. If implementation want to maintain their previous behaviour
even in the face of it now being officially "undefined", they're free to
do so.

> I think the difficulty is that the Committee's actions have been
> reinterpreted as a decision to break code which used those behaviors.

No, the standard merely describes which of those behaviours are in fact
defined, and how.

>  The
> 1974 document (which I think represents the best definition of what the C
> language was in 1974) clearly and unambiguously defines semantics which are
> sometimes useful, but are not available in the language defined by today's
> Standard.

And thank goodness. Someone else has already mentioned that you seem to want
current C to be pretty much like your C74, but I'd wager a significant
amount of beer that very few others here share that view.

> 
> > What they haven't required is that an implementation when it becomes a 
> > new implementation (maybe implementing a new version of the standard) be 
> > backwards compatible with its previous non-standard required behavior, 
> > in part because they ARE different implementations (and in fact, most 
> > 'implementations' are really to the standard a whole lot of different 
> > implementations based on the option flags given when processing, many of 
> > which may actually be non-conforming).
> 
> I think they expected that if existing implementations for machines with
> some characteristic [e.g. 16-bit big-endian silent-wraparound two's-
> complement, using 32-bit linear pointers] naturally supported certain
> useful semantics, future implementations for similar platforms would
> naturally support those same behaviors.  Compilers might offer various
> options to loosen up behavioral guarantees, but quality implementations
> should try to make clear what guarantees would be waived by which options,
> and should ensure that old semantics remain available.
> 
> For example, a compiler might treat signed integer types as being implicitly
> promotable to larger types (which could be larger than any types available
> to the user).  Given "int i1,i2; long L1,L2;" a compiler might transform
> "L1=i1*i2;" into "L1=(long)i1*i2;" or "L1+1 > L2" into "L1 >= L2", but
> allow code to force wrapping semantics with "L1=(int)(i1*i2);" or
> "(long)(L1+1) > L2".  Note that compilers wouldn't have to reach very far
> to apply the former transforms, and that the use of casts to block them is
> analogous to what's required in floating-point when using platforms that
> don't promise to refrain from using extra precision during computations
> [e.g. given "float f=16777216.0f; double d1=f+1.0f, d2=(float)(f+1.0f);"
> the value of d1 might be 16777217.0f, but d2 would be 16777216.0f].
> 
> > Most of the 'additional guarantees' that you would like to see, actually 
> > to the standard process would be great things for a supplemental 
> > standard (in the vain of POSIX), which provide limitations to the 
> > implementations and promises to the user beyond the base C standard, as 
> > an extension.
> 
> A problem I think is that people writing documentation seldom bother to
> specify things which they consider obvious.  How many shirt catalogs
> explicitly promise that shirts have two sleeves on opposite sides?

A shirt catalogue is not a standard. Standards _do_ tend to define things
that are "obvious". What's interesting to me is how convoluted and wordy
those definitions often are, probably because when one looks closely, it's
really not so "obvious" after all.

> > The Standards Committee has been somewhat reluctant to add 'optional' 
> > features to the Standard (though it does have a few, normally for 
> > special reasons). I suspect that since what you are looking for fits so 
> > nicely as an extension, I can't see it likely for them to add a bunch of 
> > new optional features to the base Standard.
> 
> For the "Standard" to really qualify as a standard, it should define classes
> of things such that knowing that x is in class X and knowing that y is in
> class Y will allow one to predict something useful about the interaction of
> objects x and y.

Um, that's exactly what the standard _does_ do; it says "if you do /this/,
you'll get /that/ result". (And, explicitly or by implication, if you do
anything different you're on your own.)

> By that definition, the so-called C "Standard" is only
> applicable to programs with constraint violations (which generally aren't
> very useful).

I don't see how that follows.

> Recognizing optional behaviors would greatly increase the value of the
> Standard by making it possible and practical to define two very useful
> categories of implementations and programs and a couple of useful guarantees
> related to them:

Taken to the extreme, _any_ implementation could be called conforming as long
as every single way in which its behaviour differs from other implementations
was documented as an option. How is this better than no standard at all?

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


#97359 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

Fromsupercat@casperkitty.com
Date2016-11-23 12:05 -0800
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<78a021a2-d6de-4f23-977f-2ea59f230fe1@googlegroups.com>
In reply to#97351
On Wednesday, November 23, 2016 at 11:01:18 AM UTC-6, someone wrote:
> On Wednesday, November 23, 2016 at 8:31:33 AM UTC-8, supercat wrote:
> > If the C89 Standard Committee was trying to maintain backward compatibility
> > (I believe they were) that would imply that they did not expect that
> > describing formerly-defined actions as invoking "Undefined Behavior" would
> > break programs that relied upon them.  Implementations would be free, after
> > all, to keep on handling those actions in useful fashion whether or not the
> > Standard mandated such treatment.
> 
> In a very real way, _nothing_ had defined behaviour before the standard,
> so claiming that formerly defined behaviour changed to undefined doesn't
> make sense. If implementation want to maintain their previous behaviour
> even in the face of it now being officially "undefined", they're free to
> do so.

Standards committees is not the only entities in the universe that
"define" things.  The 1974 document specifies how a couple of particular
implementations work.  Authors of other implementations were expected to
make them behave in analogous fashion as appropriate for the target
platform when practical.  For target platforms that were very much like
the PDP-11, almost all behaviors could be defined as "do what the PDP-11
would do".  Only when targeting platforms which were different did things
become problematic (e.g. on a PDP-11 there's no question about what (-1)<<1
should mean, but on a ones'-complement machine there would be two plausible
meanings and on a sign-magnitude machine there would be no clear meaning).

> > I think the difficulty is that the Committee's actions have been
> > reinterpreted as a decision to break code which used those behaviors.
> 
> No, the standard merely describes which of those behaviours are in fact
> defined, and how.

Which of those behaviors are defined *by the Standard*.  Before the Standard
was ratified, any compiler for two's-complement silent-wraparound hardware
which didn't evaluate (-1)<<1 as -2 would have been considered "broken".
Whether or not anything specifically defined the behavior of <<, the meaning
of left-shifting two's-complement values was most likely established even
before Dennis Ritchie was born [I don't know exactly when during the design
of the Atanasoff-Berry Computer the behavior of two's-complement math was
established, or if it had been established for something earlier, but it
would presumably have been established by the time work was discontinued in
1942].

I see no evidence that the authors of the Standard intended that it cause
anything whose meaning had been well established on certain kinds of
machines prior to the Standard's ratification to be regarded as less well
defined than it had been previously.

> >  The
> > 1974 document (which I think represents the best definition of what the C
> > language was in 1974) clearly and unambiguously defines semantics which are
> > sometimes useful, but are not available in the language defined by today's
> > Standard.
> 
> And thank goodness. Someone else has already mentioned that you seem to want
> current C to be pretty much like your C74, but I'd wager a significant
> amount of beer that very few others here share that view.

I have said that I want a language whose available semantics are a superset
of those available in C74, at least when running on platforms which share
some basic architectural features with the PDP-11 (storage consists of a
plurality of linearly-addressable octets, each integer type larger than
char is stored as two half-size chunks without padding, integer math is
performed using two's-complement hardware without overflow traps, etc.).

I wouldn't mind having to explicitly request semantics which aren't always
needed *if* there were a concise way of doing so which could be expected
to work on platforms which would naturally support the behaviors in
question.  The problem is that in many situations where when the easiest
way for compilers to support such operations on platforms where they would
be practical would be to simply treat them as defined whether the Standard
required it or not, nobody saw any need to specify any alternative which
would be unambiguously defined on all platforms that supported it.

> A shirt catalogue is not a standard. Standards _do_ tend to define things
> that are "obvious". What's interesting to me is how convoluted and wordy
> those definitions often are, probably because when one looks closely, it's
> really not so "obvious" after all.

The analogous "standard" would be the fact that shirts intended for use
by normal humans will have two sleeves, one on each side.  Many standards
do go out of their way to state the obvious, but the C89 Standard went
out of its way to avoid avoiding suggesting that any particular
implementation should be considered inferior to others, even when that
meant refraining from recommending things that almost all implementations
should support when practical, but which a few implementations might be
able to.

Most modern standards make use of terms MUST, SHOULD, etc. as defined in
RFC-2119.  In many cases, a lot of the value of a Standard comes not from
the MUST items, but from the SHOULD items.  A standard written by someone
who wants to avoid SHOULD items will often be inferior to one written by
someone who embraces them.

> > For the "Standard" to really qualify as a standard, it should define classes
> > of things such that knowing that x is in class X and knowing that y is in
> > class Y will allow one to predict something useful about the interaction of
> > objects x and y.
> 
> Um, that's exactly what the standard _does_ do; it says "if you do /this/,
> you'll get /that/ result". (And, explicitly or by implication, if you do
> anything different you're on your own.)

The Standard requires that for every conforming implementation, there must
be at least one program meeting certain criteria that the implementation
will process as described by the Standard.  Nothing in the Standard would
forbid an implementation from dying with a stack overflow (and behaving
in arbitrary fashion) when fed any other program.

> > By that definition, the so-called C "Standard" is only
> > applicable to programs with constraint violations (which generally aren't
> > very useful).
> 
> I don't see how that follows.

See above.

> > Recognizing optional behaviors would greatly increase the value of the
> > Standard by making it possible and practical to define two very useful
> > categories of implementations and programs and a couple of useful guarantees
> > related to them:
> 
> Taken to the extreme, _any_ implementation could be called conforming as long
> as every single way in which its behaviour differs from other implementations
> was documented as an option. How is this better than no standard at all?

Under my proposed rules, feeding any Selectively Conforming program to an
implementation that was at least Minimally Conforming would result in one of
two things happening:

  1. The program would function successfully.

  2. The program would fail in Implementation-Defined fashion (depending
     upon the directives it uses, such failure might be guaranteed to occur
     at compile time, or could be deferred until run time).

A program which relies upon features which some implementations support and
others do not would be less portable than one which does not rely upon such
features, but depending upon how common the feature was it could be, for
all practical purposes, "almost" as portable.  An implementation which does
not support features that are needed by many programs could be viewed as
inferior to one which does support them, but could still be very useful for
running programs that don't need such features.

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


#97308 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromAnton Shepelev <anton.txt@gmail.com>
Date2016-11-22 23:23 +0300
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<20161122232309.40aa1289366c35d048c594f3@gmail.com>
In reply to#97211
James R. Kuyper to Anton Shepelev:

> > Am  I  right  in  thinking that "Object-oriented
> > programming in C":
> >
> >     http://www.cs.rit.edu/~ats/books/ooc.pdf
> >
> > is based entirely on  the  violation  of  strict
> > aliasing?
>
> I  don't  have  time  to read that entire document
> right now.  Could you cite a particular page  that
> involves such violations?  I know that the general
> concept of "object-oriented programming in C"  (as
> opposed  to  the book of that title) does not rely
> violation of C's aliasing rules.

The author makes extensive use  of  casting  between
non-aliasing pointers.  He writes:

  1.  Passing  a  circle as a point means converting
      from a struct Circle *  to  a  struct Point *.
      We  will  refer  to  this as an up-cast from a
      subclass to a superclass -- in ANSI-C  it  can
      only  be accomplished with an explicit conver-
      sion operator or through intermediate  void  *
      values.

  2.  It  is  usually  unsound,  however,  to pass a
      point to a function intended for circles  such
      as  Circle_draw():  converting  from  a struct
      Point * to a struct Circle * is only permissi-
      ble  if the point originally was a circle.  We
      will refer to this as a down-cast from  a  su-
      perclass  to  a  subclass -- this requires ex-
      plicit conversions or void * values, too,  and
      it  can  only  be  done to pointers to objects
      that were in the subclass to begin with.

  3.     #define x(p) (((const struct Point *)(p)) -> x)
         #define y(p) (((const struct Point *)(p)) -> y)

      These macros can be applied to  a  pointer  to
      any  object  that  starts with a struct Point,
      i.e., to objects  from  any  subclass  of  our
      points.   The  technique  is  to  up-cast  the
      pointer into our superclass and reference  the
      interesting  component  there.   const  in the
      cast blocks assignments  to  the  result.   If
      const were omitted

         #define x(p) (((struct Point *)(p)) -> x)

      a  macro  call  x(p) produces an l-value which
      can be the target of an assignment.  A  better
      modification function would be the macro defi-
      nition

         #define set_x(p,v) (((struct Point *)(p)) -> x = (v))

      which produces an assignment.
-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

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


#97310 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-11-22 16:02 -0500
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<2985f44b-b799-f6bb-142e-f2c1eb9d7ee2@verizon.net>
In reply to#97308
On 11/22/2016 03:23 PM, Anton Shepelev wrote:
> James R. Kuyper to Anton Shepelev:
>
>>> Am  I  right  in  thinking that "Object-oriented
>>> programming in C":
>>>
>>>     http://www.cs.rit.edu/~ats/books/ooc.pdf
>>>
>>> is based entirely on  the  violation  of  strict
>>> aliasing?
>>
>> I  don't  have  time  to read that entire document
>> right now.  Could you cite a particular page  that
>> involves such violations?  I know that the general
>> concept of "object-oriented programming in C"  (as
>> opposed  to  the book of that title) does not rely
>> violation of C's aliasing rules.
>
> The author makes extensive use  of  casting  between
> non-aliasing pointers.  He writes:
>
>   1.  Passing  a  circle as a point means converting
>       from a struct Circle *  to  a  struct Point *.
>       We  will  refer  to  this as an up-cast from a
>       subclass to a superclass -- in ANSI-C  it  can
>       only  be accomplished with an explicit conver-
>       sion operator or through intermediate  void  *
>       values.

On page 34, he writes:
struct Circle { const struct Point _; int rad; };

Given
     struct Circle c, *pc=&c;
     struct Point p, *pp=&p;

The explicit conversion he referred to is (const struct Point *)pc, and 
it is allowed by 6.7.2.1p15. However, he's wrong about void* being the 
only other way to do this. &pc->_ is simpler and equivalent, and will 
continue to work even if some other field becomes the first member of 
struct Circle.

>   2.  It  is  usually  unsound,  however,  to pass a
>       point to a function intended for circles  such
>       as  Circle_draw():  converting  from  a struct
>       Point * to a struct Circle * is only permissi-
>       ble  if the point originally was a circle.  We

In other words, given

     pp = &c._;

then  (struct Circle*)pp is also allowed by 6.7.2.1p15. However, given:

     pp - &p;

then (struct Circle*)pp would not be allowed.

I don't see any problem with this approach. What are your concerns about it?

>       will refer to this as a down-cast from  a  su-
>       perclass  to  a  subclass -- this requires ex-
>       plicit conversions or void * values, too,  and
>       it  can  only  be  done to pointers to objects
>       that were in the subclass to begin with.
>
>   3.     #define x(p) (((const struct Point *)(p)) -> x)
>          #define y(p) (((const struct Point *)(p)) -> y)
>
>       These macros can be applied to  a  pointer  to
>       any  object  that  starts with a struct Point,
>       i.e., to objects  from  any  subclass  of  our
>       points.   The  technique  is  to  up-cast  the
>       pointer into our superclass and reference  the
>       interesting  component  there.   const  in the
>       cast blocks assignments  to  the  result.   If
>       const were omitted
>
>          #define x(p) (((struct Point *)(p)) -> x)
>
>       a  macro  call  x(p) produces an l-value which
>       can be the target of an assignment.  A  better
>       modification function would be the macro defi-
>       nition
>
>          #define set_x(p,v) (((struct Point *)(p)) -> x = (v))
>
>       which produces an assignment.
>


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


#97315 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

Fromsupercat@casperkitty.com
Date2016-11-22 14:13 -0800
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<df44fbed-7584-4154-956d-cb2bdc20da2c@googlegroups.com>
In reply to#97310
On Tuesday, November 22, 2016 at 3:02:56 PM UTC-6, James R. Kuyper wrote:
> The explicit conversion he referred to is (const struct Point *)pc, and 
> it is allowed by 6.7.2.1p15. However, he's wrong about void* being the 
> only other way to do this. &pc->_ is simpler and equivalent, and will 
> continue to work even if some other field becomes the first member of 
> struct Circle.

...
> In other words, given
> 
>      pp = &c._;
> 
> then  (struct Circle*)pp is also allowed by 6.7.2.1p15. However, given:
> 
>      pp - &p;
> 
> then (struct Circle*)pp would not be allowed.
> 
> I don't see any problem with this approach. What are your concerns about it?

Do you mean pp = &p for the second one?

The ability to take a convert a pointer to the contained "parent" object
into a pointer to the derived object is reliant upon the parent object being
the first field of the object in question; if the parent gets moved to some
other spot in the structure, code may still compile but it won't work.

Many compilers require that code with a derived-type pointer that wants to
access fields of the parent must explicitly perform the object through the
parent (e.g. if "foo" is derived from "moo", and starts with a member
"parent" of type "moo", then code wanting to access an "inherited" field x
of object *y must write foo->parent.x rather than just foo->x, even in cases
where the code in question shouldn't need to care about which members are in
the original or derived class.

If the length of the common portion isn't a multiple of its alignment
requirement it will be necessary to add padding which can't be used by
derived types.  This wastes space and may also make it impossible for
the structures to have layouts that match other APIs.

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


#97323 — Re: container_of() macro

FromNoob <root@127.0.0.1>
Date2016-11-23 01:10 +0100
SubjectRe: container_of() macro
Message-ID<o12mo3$2p5$1@dont-email.me>
In reply to#97315
On 22/11/2016 23:13, supercat@casperkitty.com wrote:

> The ability to take a convert a pointer to the contained "parent" object
> into a pointer to the derived object is reliant upon the parent object being
> the first field of the object in question; if the parent gets moved to some
> other spot in the structure, code may still compile but it won't work.

Behold Linux's container_of() macro.
(110% dependent on GCC ID behavior)

http://lxr.free-electrons.com/source/include/linux/kernel.h#L830

#define container_of(ptr, type, member) ({                      \
	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
	(type *)( (char *)__mptr - offsetof(type,member) );})

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


#97329 — Re: container_of() macro

From<william@wilbur.25thandClement.com>
Date2016-11-22 20:10 -0800
SubjectRe: container_of() macro
Message-ID<tdhfgd-q7n.ln1@wilbur.25thandClement.com>
In reply to#97323
Noob <root@127.0.0.1> wrote:
> On 22/11/2016 23:13, supercat@casperkitty.com wrote:
> 
>> The ability to take a convert a pointer to the contained "parent" object
>> into a pointer to the derived object is reliant upon the parent object being
>> the first field of the object in question; if the parent gets moved to some
>> other spot in the structure, code may still compile but it won't work.
> 
> Behold Linux's container_of() macro.
> (110% dependent on GCC ID behavior)
> 
> http://lxr.free-electrons.com/source/include/linux/kernel.h#L830
> 
> #define container_of(ptr, type, member) ({                      \
>         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
>         (type *)( (char *)__mptr - offsetof(type,member) );})
> 

AFAICT the use of typeof (and thus also the statement expression) seems to
only serve a type safety function. I don't see why the following isn't
semantically equivalent for otherwise correct code.

  (type *)((char *)(ptr) - offsetof(type, member))

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


#97364 — Re: container_of() macro

From"Chris M. Thomasson" <invalid@invalid.invalid>
Date2016-11-23 15:10 -0800
SubjectRe: container_of() macro
Message-ID<o157ip$k6u$1@dont-email.me>
In reply to#97329
On 11/22/2016 8:10 PM, william@wilbur.25thandClement.com wrote:
> Noob <root@127.0.0.1> wrote:
>> On 22/11/2016 23:13, supercat@casperkitty.com wrote:
>>
>>> The ability to take a convert a pointer to the contained "parent" object
>>> into a pointer to the derived object is reliant upon the parent object being
>>> the first field of the object in question; if the parent gets moved to some
>>> other spot in the structure, code may still compile but it won't work.
>>
>> Behold Linux's container_of() macro.
>> (110% dependent on GCC ID behavior)
>>
>> http://lxr.free-electrons.com/source/include/linux/kernel.h#L830
>>
>> #define container_of(ptr, type, member) ({                      \
>>         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
>>         (type *)( (char *)__mptr - offsetof(type,member) );})
>>
>
> AFAICT the use of typeof (and thus also the statement expression) seems to
> only serve a type safety function. I don't see why the following isn't
> semantically equivalent for otherwise correct code.
>
>   (type *)((char *)(ptr) - offsetof(type, member))
>

Looks okay to me.

FWIW, check this out wrt offsetof:
_________________________________________________
#define ALIGN_OF(mp_type) \
     offsetof( \
         struct \
         { \
               char pad_ALIGN_OF; \
               mp_type type_ALIGN_OF; \
         }, \
         type_ALIGN_OF \
     )
_________________________________________________

I posted in this thread:

https://groups.google.com/d/topic/comp.lang.c.moderated/dfFaOdBRq-0/discussion

;^)


Also, wrt container_of, here is some quick code I just typed out:
_________________________________________________
#include <stdio.h>
#include <stddef.h>

struct foo
{
     int a;
};

struct contain
{
     char a;
     double b;
     struct foo c;
     char d;
};

#define CONTAINS(mp_ptr, mp_type, mp_member) \
     ((mp_type*)(((unsigned char*)(mp_ptr)) - \
       offsetof(mp_type, mp_member)))

int main(void)
{
     struct contain c = { 'A', -.66, { 67 }, 'D' };
     struct foo* bp = &c.c;
     struct contain* cp = CONTAINS(bp, struct contain, c);

     printf("struct contain:(%p)->c(%c, %f, %d, %c)\n",
            (void*)&c, c.a, c.b, c.c.a, c.d);

     printf("struct foo:(%p)->bp(%d)\n",
            (void*)bp, bp->a);

     printf("struct contain:(%p)->cp(%c, %f, %d, %c)\n",
         (void*)cp, cp->a, cp->b, cp->c.a, cp->d);

     return 0;
}
_________________________________________________

Quite a useful construct. I have been taking advantage of it for a while 
now.

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


#97337 — Re: container_of() macro

FromDavid Brown <david.brown@hesbynett.no>
Date2016-11-23 11:31 +0100
SubjectRe: container_of() macro
Message-ID<o13r51$caa$1@dont-email.me>
In reply to#97323
On 23/11/16 01:10, Noob wrote:
> On 22/11/2016 23:13, supercat@casperkitty.com wrote:
> 
>> The ability to take a convert a pointer to the contained "parent" object
>> into a pointer to the derived object is reliant upon the parent object being
>> the first field of the object in question; if the parent gets moved to some
>> other spot in the structure, code may still compile but it won't work.
> 
> Behold Linux's container_of() macro.
> (110% dependent on GCC ID behavior)
> 
> http://lxr.free-electrons.com/source/include/linux/kernel.h#L830
> 
> #define container_of(ptr, type, member) ({                      \
> 	const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
> 	(type *)( (char *)__mptr - offsetof(type,member) );})
> 

Just as a note here, the Linux kernel is always compiled with
-fno-strict-alias.  So there is no problem if code does not follow the C
rules about which types are compatible regarding aliasing.

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


#97339 — Re: container_of() macro

FromAnton Shepelev <anton.txt@g{oogle}mail.com>
Date2016-11-23 14:07 +0300
SubjectRe: container_of() macro
Message-ID<20161123140759.1dfea18fcb556a524ab6b9b7@g{oogle}mail.com>
In reply to#97337
David Brown:

>Just  as  a  note  here, the Linux kernel is always
>compiled with -fno-strict-alias.  So  there  is  no
>problem  if  code does not follow the C rules about
>which types are compatible regarding aliasing.

And here Linus's opinion about it:

   http://stackoverflow.com/a/2959468/2862241

The second post in full is here:

   http://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg01647.html

See also the  comments  to  the  StackOverflow  post
about the way gcc follows the letter rather than the
spirit of the standard.

-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

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


#97350 — Re: container_of() macro

Fromsupercat@casperkitty.com
Date2016-11-23 08:41 -0800
SubjectRe: container_of() macro
Message-ID<692e9c17-0d2f-47da-ab4a-082bd90a79f8@googlegroups.com>
In reply to#97337
On Wednesday, November 23, 2016 at 4:31:42 AM UTC-6, David Brown wrote:
> Just as a note here, the Linux kernel is always compiled with
> -fno-strict-alias.  So there is no problem if code does not follow the C
> rules about which types are compatible regarding aliasing.

The authors of gcc have stated that they feel no obligation to uphold
behaviors which are not documented and are not mandated by the Standard,
no matter how consistently the compiler has upheld them in the past.  Does
anything in gcc's documentation actually promise that -fno-strict-alias
will cause it to always and forever regard aliasing as defined behavior,
rather than merely disabling *today's* optimizations that would break such
code but not precluding the possibility of imposing future optimizations
which would break it?

If the authors of gcc had not explicitly expressed the indicated attitude
when responding to bug reports, I would be satisfied that the only sensible
purpose of -fno-strict-alias would be to cause aliasing to be treated as
having defined behavior, but if the authors of the Standard want to reserve
the right to change any behavior that isn't explicitly documented, then
failure to explicitly document any behavior should be taken as reserving the
right to break code that uses it.

BTW, are there any versions of Unix that do not rely upon forms of aliasing
not mandated by the C or Posix standards?

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


#97747 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromAnton Shepelev <anton.txt@gmail.com>
Date2016-11-30 00:14 +0300
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<20161130001448.0acf489caa3aa31becdd5e2c@gmail.com>
In reply to#97310
James R. Kuyper to Anton Shepelev:

> > The  author  makes  extensive use if casting be-
> > tween non-aliasing pointers.  He author writes:
> >
> >   1.  Passing a circle as a point means convert-
> >       ing    from   a   struct Circle *   to   a
> >       struct Point *.  We will refer to this  as
> >       an  up-cast  from  a  subclass to a super-
> >       class -- in ANSI-C it can only  be  accom-
> >       plished with an explicit conversion opera-
> >       tor or through intermediate void * values.
> >
> On page 34, he writes:
> struct Circle { const struct Point _; int rad; };
>
> Given
>
>    struct Circle c, *pc=&c;
>    struct Point p, *pp=&p;
>
> The explicit conversion he referred to is
> (const struct Point *)pc ,
> and it is allowed by 6.7.2.1p15.

Is it the item saying that a pointer  suitably  con-
verted  shall  point the first field of a struct?  I
am sorry I have no standard at hand.

> However, he's wrong about  void*  being  the  only
> other way to do this. &pc->_ is simpler and equiv-
> alent, and will continue to work even if some oth-
> er  field  becomes the first member of struct Cir-
> cle.

In OOP this method is out of the question, because a
member should be accessible immediately from the ob-
ject at hand, without knowing the inheritance  level
at which it has been introduced.  Whereas the ->_ in
your example betrays the object's internal structure
and  the  assumption  that it is derived from Point.
What should you do if there were a three-tier  hier-
archy -- ->_->_?   For aught I know, this is allowed
under the hood but not in user code.

> >   2.  It is usually unsound, however, to pass  a
> >       point  to  a function intended for circles
> >       such as Circle_draw(): converting  from  a
> >       struct Point * to a struct Circle * is on-
> >       ly permissible if the point originally was
> >       a  circle.   We  will  refer  to this as a
> >       down-cast from  a  superclass  to  a  sub-
> >       class -- this  requires  explicit  conver-
> >       sions or void * values, too,  and  it  can
> >       only  be  done to pointers to objects that
> >       were in the subclass to begin with.
> >
> In other words, given
>
>    pp = &c._;
>
> then   (struct  Circle*)pp  is  also  allowed   by
> 6.7.2.1p15.  However, given:
>
>    pp - &p;
>
> then (struct Circle*)pp would not be allowed.
>
> I  don't see any problem with this approach.  What
> are your concerns about it?

The problem is that the author uses the  latter  ex-
pression.    In  the  appendix  "ANSI-C  Programming
Hints" he shows stark innocence of the aliasing lim-
itations:

   The  first  component of a structure starts right
   at the beginning  of  the  structure;  therefore,
   structures can be lengthened or shortened:

      struct a { int x; };
      struct c { struct a a; ... } c, * cp = & c;
      struct a * ap = & c.a;

   ANSI-C  permits  neither  implicit conversions of
   pointers  to  different  structures  nor   direct
   access to the components of an inner structure:

      cp -> a.x                ok, fully specified
      ((struct a *) cp) -> x   ok, explicit conversion (!!!)

Or am missing something?

-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

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


#97754 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-11-29 17:23 -0500
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<67f7b425-b642-398d-409b-0e767fc1ebcf@verizon.net>
In reply to#97747
On 11/29/2016 04:14 PM, Anton Shepelev wrote:
> James R. Kuyper to Anton Shepelev:
>
>>> The  author  makes  extensive use if casting be-
>>> tween non-aliasing pointers.  He author writes:
>>>
>>>   1.  Passing a circle as a point means convert-
>>>       ing    from   a   struct Circle *   to   a
>>>       struct Point *.  We will refer to this  as
>>>       an  up-cast  from  a  subclass to a super-
>>>       class -- in ANSI-C it can only  be  accom-
>>>       plished with an explicit conversion opera-
>>>       tor or through intermediate void * values.
>>>
>> On page 34, he writes:
>> struct Circle { const struct Point _; int rad; };
>>
>> Given
>>
>>    struct Circle c, *pc=&c;
>>    struct Point p, *pp=&p;
>>
>> The explicit conversion he referred to is
>> (const struct Point *)pc ,
>> and it is allowed by 6.7.2.1p15.
>
> Is it the item saying that a pointer  suitably  con-
> verted  shall  point the first field of a struct?

Yes.

>> However, he's wrong about  void*  being  the  only
>> other way to do this. &pc->_ is simpler and equiv-
>> alent, and will continue to work even if some oth-
>> er  field  becomes the first member of struct Cir-
>> cle.
>
> In OOP this method is out of the question, because a
> member should be accessible immediately from the ob-
> ject at hand, without knowing the inheritance  level
> at which it has been introduced.  Whereas the ->_ in
> your example betrays the object's internal structure
> and  the  assumption  that it is derived from Point.

The cast makes the assumption that the first actual member of struct 
Circle is an object of type struct Point, or an array of struct Point - 
either directly, or recursively because the first member has a struct 
type of which that is true.
The use of ->_, on the other hand, makes the assumption that there is 
some member of struct Circle, not necessarily the first one, with a name 
of _ and type of struct Point.

Is making an assumption about the location of the struct Point member 
any better, or any worse, than making an assumption about the name of 
that member? That depends entirely upon which assumption is more likely 
to be true. If you're certain that one assumption is valid, and are 
worried that the other one might not be, you should use the expression 
which relies upon the assumption your certain of. Otherwise, it doesn't 
matter.

> What should you do if there were a three-tier  hier-
> archy -- ->_->_?   For aught I know, this is allowed
> under the hood but not in user code.
>
>>>   2.  It is usually unsound, however, to pass  a
>>>       point  to  a function intended for circles
>>>       such as Circle_draw(): converting  from  a
>>>       struct Point * to a struct Circle * is on-
>>>       ly permissible if the point originally was
>>>       a  circle.   We  will  refer  to this as a
>>>       down-cast from  a  superclass  to  a  sub-
>>>       class -- this  requires  explicit  conver-
>>>       sions or void * values, too,  and  it  can
>>>       only  be  done to pointers to objects that
>>>       were in the subclass to begin with.
>>>
>> In other words, given
>>
>>    pp = &c._;
>>
>> then   (struct  Circle*)pp  is  also  allowed   by
>> 6.7.2.1p15.  However, given:
>>
>>    pp - &p;

Correction: that should have been
       pp = &p;

>> then (struct Circle*)pp would not be allowed.
>>
>> I  don't see any problem with this approach.  What
>> are your concerns about it?
>
> The problem is that the author uses the  latter  ex-
> pression. ...

I don't see any expression corresponding to that one in the code below:

> ...  In  the  appendix  "ANSI-C  Programming
> Hints" he shows stark innocence of the aliasing lim-
> itations:
>
>    The  first  component of a structure starts right
>    at the beginning  of  the  structure;  therefore,
>    structures can be lengthened or shortened:
>
>       struct a { int x; };
>       struct c { struct a a; ... } c, * cp = & c;
>       struct a * ap = & c.a;

The code that I said above would not be allowed would be analogous to 
the following:

        struct a a;
        ap = &a;
        (struct c*)ap

There is no such code in the sample you've given me, and no indications 
about whether or not the author is aware that such code would be 
problematic.

>    ANSI-C  permits  neither  implicit conversions of
>    pointers  to  different  structures  nor   direct
>    access to the components of an inner structure:
>
>       cp -> a.x                ok, fully specified
>       ((struct a *) cp) -> x   ok, explicit conversion (!!!)
>
> Or am missing something?

Possibly. Or maybe I'm missing something. I don't see any aliasing 
problems in the above code. Could you please identify them?

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


#97980 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromAnton Shepelev <anton.txt@gmail.com>
Date2016-12-04 18:48 +0300
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<20161204184801.3873269617033a53467cd5e1@gmail.com>
In reply to#97754
James R. Kuyper to Anton Shepelev:

> > > On page 34, he writes:
> > > struct Circle { const struct Point _; int rad;
> > > };
> > >
> > > Given
> > >
> > >    struct Circle c, *pc=&c;
> > >    struct Point p, *pp=&p;
> > >
> > > The explicit conversion he referred to is
> > > (const struct Point *)pc ,
> > > and it is allowed by 6.7.2.1p15.
> > >
> > > However, he's wrong about void* being the only
> > > other  way  to  do this. &pc->_ is simpler and
> > > equivalent, and will continue to work even  if
> > > some  other  field becomes the first member of
> > > struct Circle.
> >
> > In OOP this method is out of the  question,  be-
> > cause  a member should be accessible immediately
> > from the object at hand, without knowing the in-
> > heritance level at which it has been introduced.
> > Whereas the ->_ in your example betrays the  ob-
> > ject's  internal  structure  and  the assumption
> > that it is derived from Point.  What should  you
> > do   if   there   were   a   three-tier  hierar-
> > chy -- ->_->_?  For aught I know,  this  is  al-
> > lowed under the hood but in user code...
>
> The cast makes the assumption that the first actu-
> al member of struct Circle is an  object  of  type
> struct  Point, or an array of struct Point --  ei-
> ther directly, or recursively  because  the  first
> member  has  a  struct type of which that is true.
> The use of ->_, on the other hand, makes  the  as-
> sumption  that there is some member of struct Cir-
> cle, not necessarily the first one, with a name of
> _ and type of struct Point.

Right.

> Is  making an assumption about the location of the
> struct Point member any better, or any worse, than
> making  an  assumption about the name of that mem-
> ber?  That depends entirely upon which  assumption
> is more likely to be true.

I should rather say, on one's chosen design, because
mixing both way of access it likely a bad idea  any-
way,  and  code should be stuctured to guarantee the
correctness of one of them.

> If you're certain that one  assumption  is  valid,
> and  are  worried that the other one might not be,
> you should use the expression  which  relies  upon
> the  assumption  your  certain  of.  Otherwise, it
> doesn't matter.

It's not what I am worried about.  Rather,  I  doubt
that the by-member access agrees with the concept of
OOP's hierarchical data structures, where  the  mem-
bers  are accessed in a uniform way indifferently of
the object's line of ascent.  For example, the  syn-
tax  for accessing the coordinates of a Circle shall
not depend on the way Circle is derived, e.g.:

   Object => Circle
   (coordinates defined in the Cirlce)

   Object => Point => Circle
   (coordinates defined in Point)

   Object => RadialFigure => Point => Circle
   (coordinates defined in RadialFigure)

If that rule be violated, changing  the  implementa-
tion of Circle may break the code that uses it.

> > In  the  appendix  "ANSI-C Programming Hints" he
> > shows stark innocence of  the  aliasing  limita-
> > tions:
> >
> >    The  first  component  of  a structure starts
> >    right at  the  beginning  of  the  structure;
> >    therefore,  structures  can  be lengthened or
> >    shortened:
> >
> >       struct a { int x; };
> >       struct c { struct a a; ... } c, * cp = & c;
> >       struct a * ap = & c.a;
> >
> >    ANSI-C permits neither  implicit  conversions
> >    of   pointers  to  different  structures  nor
> >    direct access to the components of  an  inner
> >    structure:
> >
> >       cp -> a.x ok, fully specified
> >       ((struct a *) cp) -> x ok, explicit conversion (!!!)
> >
> >
> > Or am missing something?
>
> Possibly.   Or  maybe  I'm  missing  something.  I
> don't see any aliasing problems in the above code.
> Could you please identify them?

Ok.   My  initial  concern  was  about aliasing, but
since conversion here is made in-place, it cannot be
a  problem, because there is no second pointer vari-
able pointing to the same address.  Would this:

   ap = (struct a *) cp; /* alias to cp */
   ap -> x = 10;

be wrong?

-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

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


#97987 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-12-04 12:17 -0500
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<a9018b26-bafa-76d3-6fa0-a5d9e64a25b6@verizon.net>
In reply to#97980
On 12/04/2016 10:48 AM, Anton Shepelev wrote:
> James R. Kuyper to Anton Shepelev:
...
>> If you're certain that one  assumption  is  valid,
>> and  are  worried that the other one might not be,
>> you should use the expression  which  relies  upon
>> the  assumption  you're  certain  of.  Otherwise, it
>> doesn't matter.
>
> It's not what I am worried about.  Rather,  I  doubt
> that the by-member access agrees with the concept of
> OOP's hierarchical data structures, where  the  mem-
> bers  are accessed in a uniform way indifferently of
> the object's line of ascent.  For example, the  syn-
> tax  for accessing the coordinates of a Circle shall
> not depend on the way Circle is derived, e.g.:
>
>    Object => Circle
>    (coordinates defined in the Cirlce)
>
>    Object => Point => Circle
>    (coordinates defined in Point)
>
>    Object => RadialFigure => Point => Circle
>    (coordinates defined in RadialFigure)
>
> If that rule be violated, changing  the  implementa-
> tion of Circle may break the code that uses it.

You're talking about a convention used for writing object-oriented C 
code; code that conforms to that convention should always use the access 
method that is guaranteed, by use that convention, to work.

I was giving the more general rule: C code doesn't have to follow that 
convention, and if it doesn't, accessing the member by name might work 
in situations where the cast wouldn't work.

>>> In  the  appendix  "ANSI-C Programming Hints" he
>>> shows stark innocence of  the  aliasing  limita-
>>> tions:
>>>
>>>    The  first  component  of  a structure starts
>>>    right at  the  beginning  of  the  structure;
>>>    therefore,  structures  can  be lengthened or
>>>    shortened:
>>>
>>>       struct a { int x; };
>>>       struct c { struct a a; ... } c, * cp = & c;
>>>       struct a * ap = & c.a;
>>>
>>>    ANSI-C permits neither  implicit  conversions
>>>    of   pointers  to  different  structures  nor
>>>    direct access to the components of  an  inner
>>>    structure:
>>>
>>>       cp -> a.x ok, fully specified
>>>       ((struct a *) cp) -> x ok, explicit conversion (!!!)
>>>
>>>
>>> Or am missing something?
>>
>> Possibly.   Or  maybe  I'm  missing  something.  I
>> don't see any aliasing problems in the above code.
>> Could you please identify them?
>
> Ok.   My  initial  concern  was  about aliasing, but
> since conversion here is made in-place, it cannot be
> a  problem, because there is no second pointer vari-
> able pointing to the same address.  Would this:
>
>    ap = (struct a *) cp; /* alias to cp */
>    ap -> x = 10;
>
> be wrong?

No, because the result of that conversion is a pointer which is defined 
as  pointing at cp.a. That is an object with the declared type "struct 
a", which is therefore also it's effective type. Since the effective 
type of the object exactly matches the type of the lvalue that is used 
to access it, it is covered by the first item in 6.5p7: "a type 
compatible with the effective type of the object". "Two types have 
compatible type if their types are the same." (6.2.7p1)

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


#97989 — Re: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]

FromAnton Shepelev <anton.txt@gmail.com>
Date2016-12-04 22:15 +0300
SubjectRe: "Object-oriented programming in C" [was: Re: Aliasing and subtyping structs]
Message-ID<20161204221522.6297bf104191167f11cc0bbd@gmail.com>
In reply to#97987
Given the code:

   struct a { int x; };
   struct c { struct a a; ... } c, * cp = & c;
   struct a * ap = & c.a;

James R. Kuyper to Anton Shepelev:

> > Would this:
> >
> >    ap = (struct a *) cp; /* alias to cp */
> >    ap -> x
> >
> > be wrong?
>
> No,  because  the  result  of that conversion is a
> pointer which is defined  as   pointing  at  cp.a.
> That  is  an object with the declared type "struct
> a", which is therefore also it's  effective  type.
> Since  the  effective  type  of the object exactly
> matches the type of the lvalue that is used to ac-
> cess it, it is covered by the first item in 6.5p7:
> "a type compatible with the effective type of  the
> object".  "Two types have compatible type if their
> types are the same." (6.2.7p1)

Thanks.  If the first field of a  stucture  has  the
same type as that of the pointer target then pointer
conversion works.  Will I violate aliasing if I  re-
place cp with &c, i.e.:

   cp = &c;
   ap = (struct a *)&c; /* alias to cp */
   ap -> x

?

-- 
()  ascii ribbon campaign - against html e-mail
/\  http://preview.tinyurl.com/qcy6mjc [archived]

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


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

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


csiph-web