Pointer to "base" type - what does the Standard say about this?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stephan Beal

    Pointer to "base" type - what does the Standard say about this?

    Hi, all!

    Before i ask my question, i want to clarify that my question is not
    about the code i will show, but about what the C Standard says should
    happen.

    A week or so ago it occurred to me that one can implement a very basic
    form of subclassing in C (the gurus certainly already know this, but
    it was news to me). What i've done (shown below) seems to work all
    fine and well, and does exactly what i'd expect, but i'm asking about
    it because when i switched to a higher optimization level on gcc i
    started getting warnings about type-punned pointers violating "strict
    mode." That got me wondering, does it mean "strict C mode" or "strict
    GCC mode"? i don't care much about the latter, as long as i comply
    with the former. To be clear (again), my question is not GCC-specific.
    My question is whether or not the approach i've taken here is legal
    according to The Standard. i only ask because GCC suggests (at some
    optimization levels, anyway) that i might be violating some C rule
    without knowing i'm doing so.

    The code (sorry for the length - it's about as short as i can make
    this example in C while still keeping it readable):

    // ------------------- begin code
    #include <stdio.h>
    #include <stdlib.h>

    struct base_type; // unfortunate fwd decl
    // Public API for base_type objects:
    struct base_public_api
    {
    void (*func1)( struct base_type const * self );
    long (*func2)( struct base_type const * self, int );
    };
    typedef struct base_public_api base_public_api ;

    // Base-most type of the abstract interface
    struct base_type
    {
    base_public_api api;
    };
    typedef struct base_type base_type;

    // Implementation of base_type abstract interface
    struct sub_type
    {
    base_public_api api;
    int member1;
    };
    typedef struct sub_type sub_type;

    #define MARKER if(1) printf("MARKER: %s:%d:%s():
    \n",__FILE__,__ LINE__,__func__ ); if(1) printf

    #define SUBP ((sub_type const *)self)
    void impl_f1( base_type const * self )
    {
    MARKER("SUBP->member1=%d\n", SUBP->member1);
    }
    long impl_f2( base_type const * self, int x )
    {
    return SUBP->member1 * x;
    }

    // Now here's the part which is dubious: note the concrete types here:
    static const sub_type sub_type_inst = { {impl_f1,impl_f 2}, 42 };
    static base_type const * sub_inst = (base_type const*) &sub_type_in st;
    // ^^^^ "warning: dereferencing type-punned pointer will break strict-
    aliasing rules"

    int main( int argc, char const ** argv )
    {

    sub_inst->api.func1(sub_ inst);
    MARKER("func2() ==%ld\n", sub_inst->api.func2(sub_ inst, 2) );
    return 0;
    }
    // ------------------- end code

    On my box that looks like:
    stephan@jareth: ~/tmp$ ls -la inher.c
    -rw-r--r-- 1 stephan stephan 1184 2008-11-05 14:43 inher.c
    stephan@jareth: ~/tmp$ make inher
    cc inher.c -o inher
    stephan@jareth: ~/tmp$ ./inher
    MARKER: inher.c:34:impl _f1():
    SUBP->member1=42
    MARKER: inher.c:48:main ():
    func2()==84


    Am i headed down a Dark Path with this approach? Or is there a better/
    more acceptable approach to simulating single inheritance in C? (i'm
    not abject to changing the model, but i really do need some form of
    separate interface/implementation for what i'm doing.)

    Many thanks in advance for your insights.

    PS (not relevant to the question, really): what's the point of all
    that? i'm working on a library where i really need abstract base
    interfaces (with only one level of inheritance necessary), and this
    approach seems to be fairly clear (though a tad bit verbose at times).
    i've used it to implement subclasses of an abstract stream interface,
    for example, so my library can treat FILE handles and in-memory
    buffers (or client-supplied stream types, with an appropriate wrapper)
    with the same read/write API.

    PS2: my appologies for the dupe post on comp.lang.c.mod erated - i
    inadvertently posted to that group.
  • Antoninus Twink

    #2
    Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

    On 5 Nov 2008 at 15:34, Stephan Beal wrote:
    Am i headed down a Dark Path with this approach? Or is there a better/
    more acceptable approach to simulating single inheritance in C? (i'm
    not abject to changing the model, but i really do need some form of
    separate interface/implementation for what i'm doing.)
    Having subtype as "base class struct + some extra fields" and casting
    back to the base when necessary is completely ubiquitous in networking
    code based on Berkeley sockets. So if your code is meant to run on
    Windows or a *nix that does networking, then this approach will
    certainly work.

    If your interested in head-on-a-pin discussions about whether it will
    work on embedded C for a coffee machine with half the standard library
    missing, the "regulars" will no doubt be along soon with their usual
    grandstanding answers.

    Comment

    • Stephan Beal

      #3
      Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

      On Nov 5, 5:25 pm, Antoninus Twink <nos...@nospam. invalidwrote:
      Having subtype as "base class struct + some extra fields" and casting
      back to the base when necessary is completely ubiquitous in networking
      code based on Berkeley sockets.
      That's good to hear, thanks :).
      So if your code is meant to run on
      Windows or a *nix that does networking, then this approach will
      certainly work.
      The code is intended to be platform neutral (but "C" below...), and it
      now sounds like the approach i chose is also platform neutral. i was
      worried there for a while.

      As a baseline i'm trying to make sure it also compiles (and behaves
      properly) with tcc (TinyC Compiler).
      If your interested in head-on-a-pin discussions about whether it will
      work on embedded C for a coffee machine with half the standard library
      missing, the "regulars" will no doubt be along soon with their usual
      grandstanding answers.
      i'm only interested in conforming to The Standard. My programming
      won't allow me to sleep at night if i knowingly make use of a compiler-
      specific extension (with the exception of a couple very common
      extensions, like free placement of var decls in functions, instead of
      all at the front).

      Thanks for the answer - it sounds like i'm not treading any
      particularly dangerous ground here (assuming the API is used properly,
      of course).

      Comment

      • Stephan Beal

        #4
        Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

        On Nov 5, 5:44 pm, Stephan Beal <sgb...@googlem ail.comwrote:
        The code is intended to be platform neutral (but "C" below...), and it
        now sounds like the approach i chose is also platform neutral. i was
        worried there for a while.
        Doh, i spoke to soon:



        Says:

        "In C99, it is illegal to create an alias of a different type than the
        original. This is often refered to as the strict aliasing rule."

        Now i'm at an impasse - a few parts of my code rely on C99 features,
        all but 1 of them (vsscanf()) i could probably easily do without. But
        if i require C99 mode then i'm knowingly using undefined behaviour.
        That's a tough call, considering that i don't think i can reasonably
        reimplement around this limitation. Damn.

        Comment

        • Jean-Marc Bourguet

          #5
          Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

          Antoninus Twink <nospam@nospam. invalidwrites:
          On 5 Nov 2008 at 15:34, Stephan Beal wrote:
          Am i headed down a Dark Path with this approach? Or is there a better/
          more acceptable approach to simulating single inheritance in C? (i'm
          not abject to changing the model, but i really do need some form of
          separate interface/implementation for what i'm doing.)
          >
          Having subtype as "base class struct + some extra fields" and casting
          back to the base when necessary is completely ubiquitous in networking
          code based on Berkeley sockets. So if your code is meant to run on
          Windows or a *nix that does networking, then this approach will
          certainly work.
          >
          If your interested in head-on-a-pin discussions about whether it will
          work on embedded C for a coffee machine with half the standard library
          missing, the "regulars" will no doubt be along soon with their usual
          grandstanding answers.
          The problem isn't with a coffee machine -- the compiler for which will
          probably have a simple optimizer -- but with a complex optimizer which uses
          the aliasing rules to drives the optimisation. And so code will
          works... until the optimizer see an opportunity to use the fact that two
          things shouldn't alias.

          In the OP case, there is hope. Replacing

          static base_type const * sub_inst = (base_type const*) &sub_type_in st;

          by

          static base_type const * sub_inst = &sub_type_inst. api;

          will remove complains about this line. Now the only problematic part is

          ((sub_type const *)self)

          but this isn't problematic AFAIK (6.7.2.1/14 in C99 and I seem to remember
          that C90 has the same language: A pointer to a structure object, suitably
          converted, points to its initial member (or if that member is a bit-field,
          then to the unit in which it resides), and vice versa.) BTW, that reference
          shows that there isn't a need to complains about the first line.

          Yours,

          --
          Jean-Marc

          Comment

          • jameskuyper

            #6
            Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

            Stephan Beal wrote:
            ....
            // ------------------- begin code
            #include <stdio.h>
            #include <stdlib.h>
            >
            struct base_type; // unfortunate fwd decl
            // Public API for base_type objects:
            struct base_public_api
            {
            void (*func1)( struct base_type const * self );
            long (*func2)( struct base_type const * self, int );
            };
            typedef struct base_public_api base_public_api ;
            You can combine those two statements:

            typedef struct base_public_api
            {
            // details
            } base_public_api ;
            // Base-most type of the abstract interface
            struct base_type
            {
            base_public_api api;
            };
            typedef struct base_type base_type;
            >
            // Implementation of base_type abstract interface
            struct sub_type
            {
            base_public_api api;
            int member1;
            };
            typedef struct sub_type sub_type;
            ....
            // Now here's the part which is dubious: note the concrete types here:
            static const sub_type sub_type_inst = { {impl_f1,impl_f 2}, 42 };
            static base_type const * sub_inst = (base_type const*) &sub_type_in st;
            // ^^^^ "warning: dereferencing type-punned pointer will break strict-
            aliasing rules"
            There's no problem there. Section 6.7.2.1p13 says "A pointer to a
            structure object, suitably converted, points to its initial member (or
            if that member is a bit-field, then to the unit in which it resides),
            and vice versa."

            Strictly speaking, you have to apply that rule twice, and that implies
            that the correct conversion has to be:

            static_base_typ e const* sub_inst = (base type const*)
            (base_public_ap i*)&sub_type_in st;

            If we are given the fact that, for a specific set of types A, B, and
            C, where p is object of type C*, the conversion (A*)(B*)p is legal,
            the standard says nothing that allows us to conclude that (A*)(B*)p ==
            (A*)p. It doesn't even guarantee that (A*)p is also legal. However,
            in practice, I would expect this to work, and I believe that the
            intent was that it should work.

            Comment

            • Stephan Beal

              #7
              Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

              On Nov 5, 6:36 pm, Jean-Marc Bourguet <j...@bourguet. orgwrote:
              The problem isn't with a coffee machine -- the compiler for which will
              probably have a simple optimizer -- but with a complex optimizer which uses
              the aliasing rules to drives the optimisation. And so code will
              works... until the optimizer see an opportunity to use the fact that two
              things shouldn't alias.
              Optimization is certainly a potential problem. i can conceive that for
              some reason a compiler might optimize or pad these differently:

              struct sub1
              {
              base_api api;
              int m1;
              double m2;
              };

              struct sub1
              {
              base_api api;
              double m1;
              char const * m2;
              };

              but my knowledge of explicit optimizations done by any given compiler
              is pretty minimal. i'm much better versed in C++ than C.
              In the OP case, there is hope. Replacing
              >
              static base_type const * sub_inst = (base_type const*) &sub_type_in st;
              >
              by
              >
              static base_type const * sub_inst = &sub_type_inst. api;
              That was my original thought, but the point of passing (base_type
              [const]*) as the "self" argument of base_type_api was to give me a
              level of indirection which i want (for storage of subtype-specific
              data without requiring subclasses to literally redeclare the whole
              public API), and i lose that (and features based off of it) if i pass
              a (base_type_api* ) and cast it to a (sub_type*) (which in my eyes is
              just plain wrong, even if it might work in this case).
              will remove complains about this line. Now the only problematic part is
              >
              ((sub_type const *)self)
              >
              but this isn't problematic AFAIK (6.7.2.1/14 in C99 and I seem to remember
              that C90 has the same language: A pointer to a structure object, suitably
              converted, points to its initial member (or if that member is a bit-field,
              then to the unit in which it resides), and vice versa.)
              Coincidentally, i spent the last half hour reading up on that topic.
              The reading here was enlighting:



              After reading that, i'm very confused about whether using the
              "restrict" keyword might in some way help me here.

              My current conclusion is:

              a) it's technically illegal.
              b) it's largely assumed to be safe on "most" platforms.
              c) my subclasses are all private implementations (file-level scope)
              and are never referenced using their subtype outside of a single file,
              so the compiler might have a chance of knowing what i'm hoping for.
              BTW, that reference
              shows that there isn't a need to complains about the first line.
              gcc doesn't complain until i turn on -O2 or higher or turn on the -
              fstrict-aliasing flag. tcc doesn't complain at all.

              Thanks for your input :).

              Comment

              • Stephan Beal

                #8
                Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                On Nov 5, 6:47 pm, jameskuyper <jameskuy...@ve rizon.netwrote:
                You can combine those two statements:
                >
                typedef struct base_public_api
                {
                // details
                >
                } base_public_api ;
                Thanks for that. i'm far more used to C++ than C (been away from C
                since 1995 or so), so i'm not all caught up yet.
                There's no problem there. Section 6.7.2.1p13 says "A pointer to a
                structure object, suitably converted, points to its initial member (or
                if that member is a bit-field, then to the unit in which it resides),
                and vice versa."
                AND vice versa? That changes things. So that means that i could cast
                the (base_type_api* ) itself back to the original subclass which
                contains it (provided i use it as we've shown here)?

                So does that imply that the following is actually legal? (warning -
                uncompiled)

                typedef struct API
                {
                int (*func1)( struct API * );
                // ... more API ...
                } API;

                typedef struct Foo
                {
                API api;
                int val;
                } Foo;

                int func1_Foo( API *x )
                {
                return (Foo*)x;
                }

                ....

                Foo foo;
                foo.api.func1 = func1_Foo;
                printf("%d\n",f oo.api.func1( &foo ));


                If that's legal then i'm happy (though a bit perplexed as to why it
                would be allowed).
                If we are given the fact that, for a specific set of types A, B, and
                C, where p is object of type C*, the conversion (A*)(B*)p is legal,
                the standard says nothing that allows us to conclude that (A*)(B*)p ==
                (A*)p. It doesn't even guarantee that (A*)p is also legal.
                Those last two parts: fair enough, and i think i understand why that
                must be so, but it is philosophically unsettling nonetheless.
                However,
                in practice, I would expect this to work, and I believe that the
                intent was that it should work.
                MY intent is for it to work, certainly ;). i just hope i'm not
                violating anyone's bits by doing this.

                Thanks for your insightful reply :).

                Comment

                • jameskuyper

                  #9
                  Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                  jameskuyper wrote:
                  Stephan Beal wrote:
                  ...
                  // ------------------- begin code
                  #include <stdio.h>
                  #include <stdlib.h>

                  struct base_type; // unfortunate fwd decl
                  // Public API for base_type objects:
                  struct base_public_api
                  {
                  void (*func1)( struct base_type const * self );
                  long (*func2)( struct base_type const * self, int );
                  };
                  typedef struct base_public_api base_public_api ;
                  ....
                  // Base-most type of the abstract interface
                  struct base_type
                  {
                  base_public_api api;
                  };
                  typedef struct base_type base_type;

                  // Implementation of base_type abstract interface
                  struct sub_type
                  {
                  base_public_api api;
                  int member1;
                  };
                  typedef struct sub_type sub_type;
                  >
                  ...
                  // Now here's the part which is dubious: note the concrete types here:
                  static const sub_type sub_type_inst = { {impl_f1,impl_f 2}, 42 };
                  static base_type const * sub_inst = (base_type const*) &sub_type_in st;
                  // ^^^^ "warning: dereferencing type-punned pointer will break strict-
                  aliasing rules"
                  >
                  There's no problem there.
                  [Nonsense]

                  Sorry about that. I got mixed up because I misread your code. I was
                  somehow got confused while reading your code, and was under the
                  impression that sub_type_inst had a member of type base_public_api
                  (which was correct), and that base_public_api had a member of type
                  base_type (which is exactly backwards). You can only perform such a
                  conversion by defining a union of both types, and only when the
                  original pointer points to one of the members of such a union.

                  Comment

                  • Stephan Beal

                    #10
                    Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                    On Nov 5, 7:23 pm, jameskuyper <jameskuy...@ve rizon.netwrote:
                    Sorry about that. I got mixed up because I misread your code. I was
                    somehow got confused while reading your code, and was under the
                    impression that sub_type_inst had a member of type base_public_api
                    (which was correct), and that base_public_api had a member of type
                    base_type (which is exactly backwards).
                    It was a good try, though :).
                    You can only perform such a
                    conversion by defining a union of both types, and only when the
                    original pointer points to one of the members of such a union.
                    i'm considering the union option. However, that would require that i
                    use all the concrete subtypes in the public union. Right now my
                    subtypes are all static/file-scope implementations , so that wouldn't
                    be possible without revealing those types, some of which require
                    optional add-on functionality like sqlite3 (which the subclasses hide
                    in the current API).

                    In the off chance that you'd like to see the actual code, visit here:



                    give in the user name "anonymous" with password "anonymous" (that's an
                    anti-bot feature of the hosting SCM software), click Login, and you'll
                    see the files. The base types are declared in c11n_io.h (search for
                    "_api api;") and a couple concrete impls of the c11n_stream base are
                    in c11n_stream_*.c . (c11n_io_handle r_*.c are also relevant but
                    significantly more complex because they are grammar parser
                    implementations .)

                    Again, thanks for the insights!

                    Comment

                    • Andrey Tarasevich

                      #11
                      Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                      Stephan Beal wrote:
                      >
                      Many thanks in advance for your insights.
                      >
                      The technique you describe has been used in C since forever. The other
                      posters already gave you a quote form the language specification, which
                      validates this useful technique, and which was actually included into
                      the language specification specifically for that purpose.

                      (The valid struct<->first member conversion actually made it into C++
                      specification as well).

                      --
                      Best regards,
                      Andrey Tarasevich

                      Comment

                      • Stephan Beal

                        #12
                        Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                        On Nov 5, 7:57 pm, Hallvard B Furuseth <h.b.furus...@u sit.uio.no>
                        wrote:
                        Stephan Beal writes:
                        Doh, i spoke to soon:
                        >>
                        Says:
                        >
                        "In C99, it is illegal to create an alias of a different type than the
                        original. This is often refered to as the strict aliasing rule."
                        >
                        Not quite. What is illegal, with some exceptions, is to access an
                        <HUGE snip

                        Wow, thanks for that! Now i've got some reading to do :).

                        The base struct macro you show is basically how i'm initiaizing my
                        subclasses, with the exception that i have on extra degree of
                        indirection - the subtypes hold an object which itself holds the
                        common API (that approach seems to simplify maintenance of the
                        subclass implementations in the event of a change in the base API).

                        Comment

                        • Stephen Sprunk

                          #13
                          Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                          Stephan Beal wrote:
                          On Nov 5, 6:36 pm, Jean-Marc Bourguet <j...@bourguet. orgwrote:
                          >The problem isn't with a coffee machine -- the compiler for which will
                          >probably have a simple optimizer -- but with a complex optimizer which uses
                          >the aliasing rules to drives the optimisation. And so code will
                          >works... until the optimizer see an opportunity to use the fact that two
                          >things shouldn't alias.
                          >
                          Optimization is certainly a potential problem. i can conceive that for
                          some reason a compiler might optimize or pad these differently:
                          >
                          struct sub1
                          {
                          base_api api;
                          int m1;
                          double m2;
                          };
                          >
                          struct sub1
                          {
                          base_api api;
                          double m1;
                          char const * m2;
                          };
                          >
                          but my knowledge of explicit optimizations done by any given compiler
                          is pretty minimal. i'm much better versed in C++ than C.
                          Those structs will likely be padded differently, yes, but you _should_
                          be able to cast from one to the other as long as you only access the
                          initial elements that they have in common (in this case, only "api").
                          Compilers are required to pad consistently enough that, as far into the
                          struct as the element types remain the same, they will be at the same
                          offsets; this is deliberate to allow casts to access them.

                          Think about this example:

                          struct point {
                          int x;
                          int y;
                          };
                          struct circle {
                          int x;
                          int y;
                          int radius;
                          };
                          struct rect {
                          int x;
                          int y;
                          int width;
                          int height;
                          };

                          Any time you need a struct point, you can safely cast a struct circle
                          and access x or y. This is very, very bare-bones inheritance and
                          polymorphism.
                          >In the OP case, there is hope. Replacing
                          >>
                          >static base_type const * sub_inst = (base_type const*) &sub_type_in st;
                          >>
                          >by
                          >>
                          >static base_type const * sub_inst = &sub_type_inst. api;
                          >
                          That was my original thought, but the point of passing (base_type
                          [const]*) as the "self" argument of base_type_api was to give me a
                          level of indirection which i want (for storage of subtype-specific
                          data without requiring subclasses to literally redeclare the whole
                          public API), and i lose that (and features based off of it) if i pass
                          a (base_type_api* ) and cast it to a (sub_type*) (which in my eyes is
                          just plain wrong, even if it might work in this case).
                          You could also do the above as:

                          struct point {
                          int x;
                          int y;
                          };
                          struct circle {
                          struct point center;
                          int radius;
                          };

                          The syntax to access x and y isn't quite as pretty, but the layout in
                          memory will be the same (a pointer to a struct is guaranteed to be
                          equivalent to a pointer to its first element) and the compiler should be
                          quiet if you cast a struct circle to a struct point.

                          I haven't read all your code due to the length, so I'm not entirely sure
                          this helps, but I've used the same tricks in OO code of my own.
                          gcc doesn't complain until i turn on -O2 or higher or turn on the -
                          fstrict-aliasing flag. tcc doesn't complain at all.
                          If TCC doesn't complain, it probably doesn't have enough optimizing
                          intelligence to care about aliasing problems. GCC is pretty aggressive
                          in that area, but there's a huge cost in complexity to detect aliasing
                          (or lack thereof), which TCC probably can't afford given its name.

                          S

                          Comment

                          • jameskuyper

                            #14
                            Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                            Stephen Sprunk wrote:
                            ....
                            Those structs will likely be padded differently, yes, but you _should_
                            be able to cast from one to the other as long as you only access the
                            initial elements that they have in common (in this case, only "api").
                            Compilers are required to pad consistently enough that, as far into the
                            struct as the element types remain the same, they will be at the same
                            offsets; this is deliberate to allow casts to access them.
                            The relevant section of the standard makes that guarantee only if the
                            two structs are members of the same union. In practice, it generally
                            works for a much wider range of cases than the ones guaranteed by the
                            standard.

                            Comment

                            • Eric Sosman

                              #15
                              Re: Pointer to &quot;base&quot ; type - what does the Standard say about this?

                              Stephen Sprunk wrote:
                              Stephan Beal wrote:
                              >>
                              >Optimization is certainly a potential problem. i can conceive that for
                              >some reason a compiler might optimize or pad these differently:
                              >>
                              >struct sub1
                              >{
                              > base_api api;
                              > int m1;
                              > double m2;
                              >};
                              >>
                              >struct sub1
                              'sub2', I think?
                              >{
                              > base_api api;
                              > double m1;
                              > char const * m2;
                              >};
                              >>
                              >but my knowledge of explicit optimizations done by any given compiler
                              >is pretty minimal. i'm much better versed in C++ than C.
                              >
                              Those structs will likely be padded differently, yes, but you _should_
                              be able to cast from one to the other as long as you only access the
                              initial elements that they have in common (in this case, only "api").
                              Compilers are required to pad consistently enough that, as far into the
                              struct as the element types remain the same, they will be at the same
                              offsets; this is deliberate to allow casts to access them.
                              [...]
                              See James Kuyper's response, but the struct layout is not the
                              only issue. Even if the layouts are as you want them, the compiler
                              is allowed to "know" that a `struct sub1*' and a `struct sub2*' do
                              not point to the same thing (see Hallvard Furuseth's response). An
                              aggressive optimizer might assume that storing to the `api' element
                              of something pointed at by a `struct sub1*' does not affect the `api'
                              element of something pointed at by a `struct sub2*', and if in fact
                              they point at the same memory odd things could happen.

                              One clean way to handle this is to pack all the allied types
                              into a union, but this requires that you know all those types up
                              front, which can be irksome. Another clean way to handle it is to
                              use a `base_api*' and point it at the `api' element of whichever
                              structs you're dealing with. Since the `api' is the first element
                              in each struct, it is always safe to convert the struct pointer to
                              a `base_api*' and back.

                              --
                              Eric.Sosman@sun .com

                              Comment

                              Working...